xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_main.c (revision 0626a4da6c07f30da06dd6747e8cc290a60371d8)
1 /*
2  * Copyright (c) 2017-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 /**
20  * DOC: wlan_serialization_main.c
21  * This file defines the important functions pertinent to
22  * serialization to initialize and de-initialize the
23  * component.
24  */
25 #ifdef CONFIG_SERIALIZATION_V1
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 
35 struct serialization_legacy_callback ser_legacy_cb;
36 
37 QDF_STATUS wlan_serialization_psoc_close(struct wlan_objmgr_psoc *psoc)
38 {
39 	QDF_STATUS status;
40 	struct wlan_serialization_psoc_priv_obj *ser_soc_obj =
41 		wlan_serialization_get_psoc_priv_obj(psoc);
42 
43 	if (!ser_soc_obj) {
44 		serialization_err("invalid ser_soc_obj");
45 		return QDF_STATUS_E_FAILURE;
46 	}
47 	/* clean up all timers before exiting */
48 	status = wlan_serialization_cleanup_all_timers(ser_soc_obj);
49 	if (status != QDF_STATUS_SUCCESS)
50 		serialization_err("ser cleanning up all timer failed");
51 
52 	qdf_mem_free(ser_soc_obj->timers);
53 	ser_soc_obj->timers = NULL;
54 	ser_soc_obj->max_active_cmds = 0;
55 
56 	return status;
57 }
58 
59 QDF_STATUS wlan_serialization_psoc_open(struct wlan_objmgr_psoc *psoc)
60 {
61 	uint8_t pdev_count;
62 	struct wlan_serialization_psoc_priv_obj *ser_soc_obj =
63 		wlan_serialization_get_psoc_priv_obj(psoc);
64 
65 	if (!ser_soc_obj) {
66 		serialization_err("invalid ser_soc_obj");
67 		return QDF_STATUS_E_FAILURE;
68 	}
69 	/* TODO:Get WLAN_SERIALIZATION_MAX_ACTIVE_SCAN_CMDS frm service ready */
70 	pdev_count = wlan_psoc_get_pdev_count(psoc);
71 	ser_soc_obj->max_active_cmds = WLAN_SERIALIZATION_MAX_ACTIVE_SCAN_CMDS +
72 		pdev_count;
73 	ser_soc_obj->timers =
74 		qdf_mem_malloc(sizeof(struct wlan_serialization_timer) *
75 				ser_soc_obj->max_active_cmds);
76 	if (NULL == ser_soc_obj->timers) {
77 		serialization_alert("Mem alloc failed for ser timers");
78 		return QDF_STATUS_E_NOMEM;
79 	}
80 
81 	return QDF_STATUS_SUCCESS;
82 }
83 
84 /**
85  * wlan_serialization_psoc_obj_create_notification() - PSOC obj create callback
86  * @psoc: PSOC object
87  * @arg_list: Variable argument list
88  *
89  * This callback is registered with object manager during initialization and
90  * when obj manager gets its turn to create the object, it would notify each
91  * component with the corresponding callback registered to inform the
92  * completion of the creation of the respective object.
93  *
94  * Return: QDF Status
95  */
96 static QDF_STATUS wlan_serialization_psoc_obj_create_notification(
97 		struct wlan_objmgr_psoc *psoc, void *arg_list)
98 {
99 	struct wlan_serialization_psoc_priv_obj *soc_ser_obj;
100 
101 	soc_ser_obj =
102 		qdf_mem_malloc(sizeof(*soc_ser_obj));
103 	if (NULL == soc_ser_obj) {
104 		serialization_alert("Mem alloc failed for ser psoc priv obj");
105 		return QDF_STATUS_E_NOMEM;
106 	}
107 	wlan_objmgr_psoc_component_obj_attach(psoc,
108 			WLAN_UMAC_COMP_SERIALIZATION, soc_ser_obj,
109 			QDF_STATUS_SUCCESS);
110 	serialization_debug("ser psoc obj created");
111 
112 	return QDF_STATUS_SUCCESS;
113 }
114 
115 /**
116  * wlan_serialization_destroy_cmd_pool() - Destroy the global cmd pool
117  * @ser_pdev_obj: Serialization private pdev object
118  *
119  * Return: None
120  */
121 static void wlan_serialization_destroy_cmd_pool(
122 		  struct wlan_serialization_pdev_priv_obj *ser_pdev_obj)
123 {
124 
125 	qdf_list_node_t *node = NULL;
126 	struct wlan_serialization_command_list *cmd_list;
127 
128 	while (!qdf_list_empty(&ser_pdev_obj->global_cmd_pool_list)) {
129 		qdf_list_remove_front(&ser_pdev_obj->global_cmd_pool_list,
130 				&node);
131 		cmd_list = (struct wlan_serialization_command_list *)node;
132 		serialization_debug("Node being freed from global pool %pK",
133 				cmd_list);
134 		qdf_mem_free(cmd_list);
135 
136 	}
137 	qdf_list_destroy(&ser_pdev_obj->global_cmd_pool_list);
138 }
139 
140 /**
141  * wlan_serialization_create_cmd_pool() - Create the global cmd pool
142  * @pdev: PDEV Object
143  * @ser_pdev_obj: Serialization private pdev object
144  *
145  * Global command pool of memory is created here.
146  * It is safe to allocate memory individually for each command rather than
147  * requesting for a huge chunk of memory at once.
148  *
149  * The individual command nodes allocated above will keep moving between
150  * the active, pending and global pool lists dynamically, but all the
151  * memory will be freed during driver unload only.
152  *
153  * Return: QDF Status
154  */
155 static QDF_STATUS
156 wlan_serialization_create_cmd_pool(struct wlan_objmgr_pdev *pdev,
157 		struct wlan_serialization_pdev_priv_obj *ser_pdev_obj)
158 {
159 	struct wlan_serialization_command_list *cmd_list_ptr;
160 	uint8_t i;
161 
162 	for (i = 0; i < WLAN_SERIALIZATION_MAX_GLOBAL_POOL_CMDS; i++) {
163 		cmd_list_ptr = qdf_mem_malloc(sizeof(*cmd_list_ptr));
164 		if (NULL == cmd_list_ptr) {
165 			serialization_alert("Mem alloc failed for cmd node");
166 			wlan_serialization_destroy_cmd_pool(ser_pdev_obj);
167 			return QDF_STATUS_E_NOMEM;
168 		}
169 		qdf_list_insert_back(
170 				&ser_pdev_obj->global_cmd_pool_list,
171 				&cmd_list_ptr->node);
172 		cmd_list_ptr->cmd_in_use = 0;
173 		serialization_debug("Created node at %pK and inserted to pool",
174 				cmd_list_ptr);
175 	}
176 
177 	return QDF_STATUS_SUCCESS;
178 }
179 
180 
181 /**
182  * wlan_serialization_pdev_obj_create_notification() - PDEV obj create callback
183  * @pdev: PDEV object
184  * @arg_list: Variable argument list
185  *
186  * This callback is registered with object manager during initialization and
187  * when obj manager gets its turn to create the object, it would notify each
188  * component with the corresponding callback registered to inform the
189  * completion of the creation of the respective object.
190  *
191  * Return: QDF Status
192  */
193 static QDF_STATUS wlan_serialization_pdev_obj_create_notification(
194 		struct wlan_objmgr_pdev *pdev, void *arg_list)
195 {
196 	struct wlan_serialization_pdev_priv_obj *ser_pdev_obj;
197 	QDF_STATUS status;
198 
199 	ser_pdev_obj =
200 		qdf_mem_malloc(sizeof(*ser_pdev_obj));
201 	if (NULL == ser_pdev_obj) {
202 		serialization_alert("Mem alloc failed for ser pdev obj");
203 		return QDF_STATUS_E_NOMEM;
204 	}
205 	status = wlan_serialization_create_lock(ser_pdev_obj);
206 	if (status != QDF_STATUS_SUCCESS) {
207 		serialization_err("Failed to create serialization lock");
208 		return status;
209 	}
210 	qdf_list_create(&ser_pdev_obj->active_list,
211 			WLAN_SERIALIZATION_MAX_ACTIVE_CMDS);
212 	qdf_list_create(&ser_pdev_obj->pending_list,
213 			WLAN_SERIALIZATION_MAX_GLOBAL_POOL_CMDS);
214 	qdf_list_create(&ser_pdev_obj->active_scan_list,
215 			WLAN_SERIALIZATION_MAX_ACTIVE_SCAN_CMDS);
216 	qdf_list_create(&ser_pdev_obj->pending_scan_list,
217 			WLAN_SERIALIZATION_MAX_GLOBAL_POOL_CMDS);
218 	qdf_list_create(&ser_pdev_obj->global_cmd_pool_list,
219 			WLAN_SERIALIZATION_MAX_GLOBAL_POOL_CMDS);
220 	status = wlan_serialization_create_cmd_pool(pdev, ser_pdev_obj);
221 	if (status != QDF_STATUS_SUCCESS) {
222 		serialization_err("ser_pdev_obj failed status %d", status);
223 		return status;
224 	}
225 	status = wlan_objmgr_pdev_component_obj_attach(pdev,
226 		WLAN_UMAC_COMP_SERIALIZATION, ser_pdev_obj,
227 		QDF_STATUS_SUCCESS);
228 	if (status != QDF_STATUS_SUCCESS) {
229 		serialization_err("serialization pdev obj attach failed");
230 		return status;
231 	}
232 
233 	return status;
234 }
235 
236 /**
237  * wlan_serialization_psoc_obj_destroy_notification() - PSOC obj delete callback
238  * @psoc: PSOC object
239  * @arg_list: Variable argument list
240  *
241  * This callback is registered with object manager during initialization and
242  * when obj manager gets its turn to delete the object, it would notify each
243  * component with the corresponding callback registered to inform the
244  * completion of the deletion of the respective object.
245  *
246  * Return: QDF Status
247  */
248 static QDF_STATUS wlan_serialization_psoc_obj_destroy_notification(
249 		struct wlan_objmgr_psoc *psoc, void *arg_list)
250 {
251 	QDF_STATUS status;
252 	struct wlan_serialization_psoc_priv_obj *ser_soc_obj =
253 		wlan_serialization_get_psoc_priv_obj(psoc);
254 
255 	if (NULL == ser_soc_obj) {
256 		serialization_err("invalid ser_soc_obj");
257 		return QDF_STATUS_E_FAULT;
258 	}
259 	status = wlan_objmgr_psoc_component_obj_detach(psoc,
260 			WLAN_UMAC_COMP_SERIALIZATION,
261 			ser_soc_obj);
262 	if (status != QDF_STATUS_SUCCESS)
263 		serialization_err("ser psoc private obj detach failed");
264 	serialization_debug("ser psoc obj deleted with status %d", status);
265 	qdf_mem_free(ser_soc_obj);
266 
267 	return status;
268 }
269 
270 /**
271  * wlan_serialization_pdev_obj_destroy_notification() - PDEV obj delete callback
272  * @pdev: PDEV object
273  * @arg_list: Variable argument list
274  *
275  * This callback is registered with object manager during initialization and
276  * when obj manager gets its turn to delete the object, it would notify each
277  * component with the corresponding callback registered to inform the
278  * completion of the deletion of the respective object.
279  *
280  * Return: QDF Status
281  */
282 static QDF_STATUS wlan_serialization_pdev_obj_destroy_notification(
283 		struct wlan_objmgr_pdev *pdev, void *arg_list)
284 {
285 	QDF_STATUS status;
286 	struct wlan_serialization_pdev_priv_obj *ser_pdev_obj =
287 		wlan_serialization_get_pdev_priv_obj(pdev);
288 
289 	status = wlan_objmgr_pdev_component_obj_detach(pdev,
290 			WLAN_UMAC_COMP_SERIALIZATION, ser_pdev_obj);
291 	wlan_serialization_destroy_list(ser_pdev_obj,
292 					&ser_pdev_obj->active_list);
293 	wlan_serialization_destroy_list(ser_pdev_obj,
294 					&ser_pdev_obj->pending_list);
295 	wlan_serialization_destroy_list(ser_pdev_obj,
296 					&ser_pdev_obj->active_scan_list);
297 	wlan_serialization_destroy_list(ser_pdev_obj,
298 					&ser_pdev_obj->pending_scan_list);
299 	wlan_serialization_destroy_cmd_pool(ser_pdev_obj);
300 	serialization_debug("ser pdev obj detached with status %d", status);
301 	status = wlan_serialization_destroy_lock(ser_pdev_obj);
302 	if (status != QDF_STATUS_SUCCESS)
303 		serialization_err("Failed to destroy serialization lock");
304 	qdf_mem_free(ser_pdev_obj);
305 
306 	return status;
307 }
308 
309 /**
310  * wlan_serialization_vdev_obj_create_notification() - VDEV obj create callback
311  * @vdev: VDEV object
312  * @arg_list: Variable argument list
313  *
314  * This callback is registered with object manager during initialization and
315  * when obj manager gets its turn to create the object, it would notify each
316  * component with the corresponding callback registered to inform the
317  * completion of the creation of the respective object.
318  *
319  * Return: QDF Status
320  */
321 static QDF_STATUS wlan_serialization_vdev_obj_create_notification(
322 		struct wlan_objmgr_vdev *vdev, void *arg_list)
323 {
324 	return QDF_STATUS_SUCCESS;
325 }
326 
327 /**
328  * wlan_serialization_vdev_obj_destroy_notification() - vdev obj delete callback
329  * @vdev: VDEV object
330  * @arg_list: Variable argument list
331  *
332  * This callback is registered with object manager during initialization and
333  * when obj manager gets its turn to delete the object, it would notify each
334  * component with the corresponding callback registered to inform the
335  * completion of the deletion of the respective object.
336  *
337  * Return: QDF Status
338  */
339 static QDF_STATUS wlan_serialization_vdev_obj_destroy_notification(
340 		struct wlan_objmgr_vdev *vdev, void *arg_list)
341 {
342 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
343 
344 	if (!ser_legacy_cb.serialization_purge_cmd_list)
345 		return QDF_STATUS_SUCCESS;
346 
347 	serialization_debug("for vdev_id[%d] vdev[%pK] flush all cmds",
348 			  vdev_id, vdev);
349 	ser_legacy_cb.serialization_purge_cmd_list(wlan_vdev_get_psoc(vdev),
350 			vdev, false, false, false, false, true);
351 
352 	return QDF_STATUS_SUCCESS;
353 }
354 
355 QDF_STATUS wlan_serialization_init(void)
356 {
357 	QDF_STATUS status = QDF_STATUS_SUCCESS;
358 
359 	status = wlan_objmgr_register_psoc_create_handler(
360 			WLAN_UMAC_COMP_SERIALIZATION,
361 			wlan_serialization_psoc_obj_create_notification, NULL);
362 	if (status != QDF_STATUS_SUCCESS) {
363 		serialization_err("Failed to reg soc ser obj create handler");
364 		goto err_psoc_create;
365 	}
366 
367 	status = wlan_objmgr_register_psoc_destroy_handler(
368 			WLAN_UMAC_COMP_SERIALIZATION,
369 			wlan_serialization_psoc_obj_destroy_notification, NULL);
370 	if (status != QDF_STATUS_SUCCESS) {
371 		serialization_err("Failed to reg soc ser obj delete handler");
372 		goto err_psoc_delete;
373 	}
374 
375 	status = wlan_objmgr_register_pdev_create_handler(
376 			WLAN_UMAC_COMP_SERIALIZATION,
377 			wlan_serialization_pdev_obj_create_notification, NULL);
378 	if (status != QDF_STATUS_SUCCESS) {
379 		serialization_err("Failed to reg pdev ser obj create handler");
380 		goto err_pdev_create;
381 	}
382 
383 	status = wlan_objmgr_register_pdev_destroy_handler(
384 			WLAN_UMAC_COMP_SERIALIZATION,
385 			wlan_serialization_pdev_obj_destroy_notification, NULL);
386 	if (status != QDF_STATUS_SUCCESS) {
387 		serialization_err("Failed to reg pdev ser obj delete handler");
388 		goto err_pdev_delete;
389 	}
390 
391 	status = wlan_objmgr_register_vdev_create_handler(
392 			WLAN_UMAC_COMP_SERIALIZATION,
393 			wlan_serialization_vdev_obj_create_notification, NULL);
394 	if (status != QDF_STATUS_SUCCESS) {
395 		serialization_err("Failed to reg vdev ser obj create handler");
396 		goto err_vdev_create;
397 	}
398 
399 	status = wlan_objmgr_register_vdev_destroy_handler(
400 			WLAN_UMAC_COMP_SERIALIZATION,
401 			wlan_serialization_vdev_obj_destroy_notification, NULL);
402 	if (status != QDF_STATUS_SUCCESS) {
403 		serialization_err("Failed to reg vdev ser obj delete handler");
404 		goto err_vdev_delete;
405 	}
406 	serialization_debug("serialization handlers registered with obj mgr");
407 	/*
408 	 * Initialize the structure so all callbacks are registered
409 	 * initially as NULL.
410 	 */
411 	qdf_mem_zero(&ser_legacy_cb, sizeof(ser_legacy_cb));
412 
413 	return QDF_STATUS_SUCCESS;
414 
415 err_vdev_delete:
416 	wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_SERIALIZATION,
417 			wlan_serialization_vdev_obj_create_notification, NULL);
418 err_vdev_create:
419 	wlan_objmgr_unregister_pdev_destroy_handler(
420 			WLAN_UMAC_COMP_SERIALIZATION,
421 			wlan_serialization_pdev_obj_destroy_notification, NULL);
422 err_pdev_delete:
423 	wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_SERIALIZATION,
424 			wlan_serialization_pdev_obj_create_notification, NULL);
425 err_pdev_create:
426 	wlan_objmgr_unregister_psoc_destroy_handler(
427 			WLAN_UMAC_COMP_SERIALIZATION,
428 			wlan_serialization_psoc_obj_destroy_notification, NULL);
429 err_psoc_delete:
430 	wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_SERIALIZATION,
431 			 wlan_serialization_psoc_obj_create_notification, NULL);
432 err_psoc_create:
433 	return status;
434 
435 }
436 
437 QDF_STATUS wlan_serialization_deinit(void)
438 {
439 	QDF_STATUS status;
440 	QDF_STATUS ret_status = QDF_STATUS_SUCCESS;
441 
442 	status = wlan_objmgr_unregister_psoc_create_handler(
443 			WLAN_UMAC_COMP_SERIALIZATION,
444 			wlan_serialization_psoc_obj_create_notification,
445 			NULL);
446 	if (status != QDF_STATUS_SUCCESS) {
447 		serialization_err("unreg fail for psoc ser obj create notf:%d",
448 				status);
449 		ret_status = QDF_STATUS_E_FAILURE;
450 	}
451 	status = wlan_objmgr_unregister_psoc_destroy_handler(
452 			WLAN_UMAC_COMP_SERIALIZATION,
453 			wlan_serialization_psoc_obj_destroy_notification,
454 			NULL);
455 	if (status != QDF_STATUS_SUCCESS) {
456 		serialization_err("unreg fail for psoc ser obj destroy notf:%d",
457 				status);
458 		ret_status = QDF_STATUS_E_FAILURE;
459 	}
460 
461 	status = wlan_objmgr_unregister_pdev_create_handler(
462 			WLAN_UMAC_COMP_SERIALIZATION,
463 			wlan_serialization_pdev_obj_create_notification,
464 			NULL);
465 	if (status != QDF_STATUS_SUCCESS) {
466 		serialization_err("unreg fail for pdev ser obj create notf:%d",
467 				status);
468 		ret_status = QDF_STATUS_E_FAILURE;
469 	}
470 
471 	status = wlan_objmgr_unregister_pdev_destroy_handler(
472 			WLAN_UMAC_COMP_SERIALIZATION,
473 			wlan_serialization_pdev_obj_destroy_notification,
474 			NULL);
475 	if (status != QDF_STATUS_SUCCESS) {
476 		serialization_err("unreg fail for pdev ser destroy notf:%d",
477 				status);
478 		ret_status = QDF_STATUS_E_FAILURE;
479 	}
480 
481 	serialization_alert("deregistered callbacks with obj mgr successfully");
482 	/*
483 	 * Initialize the structure so all callbacks are registered
484 	 * initially as NULL.
485 	 */
486 	qdf_mem_zero(&ser_legacy_cb, sizeof(ser_legacy_cb));
487 
488 	return ret_status;
489 }
490 #else /* New serialition code*/
491 #include <qdf_status.h>
492 #include <qdf_list.h>
493 #include <wlan_objmgr_cmn.h>
494 #include <wlan_objmgr_global_obj.h>
495 #include <wlan_objmgr_psoc_obj.h>
496 #include "wlan_serialization_main_i.h"
497 #include "wlan_serialization_rules_i.h"
498 #include "wlan_serialization_utils_i.h"
499 
500 struct serialization_legacy_callback ser_legacy_cb;
501 
502 QDF_STATUS wlan_serialization_psoc_close(struct wlan_objmgr_psoc *psoc)
503 {
504 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
505 	struct wlan_ser_psoc_obj *ser_soc_obj =
506 		wlan_serialization_get_psoc_obj(psoc);
507 
508 	ser_enter();
509 
510 	if (!ser_soc_obj) {
511 		ser_err("invalid ser_soc_obj");
512 		goto error;
513 	}
514 	/* clean up all timers before exiting */
515 	status = wlan_serialization_cleanup_all_timers(ser_soc_obj);
516 	if (status != QDF_STATUS_SUCCESS)
517 		ser_err("ser cleanning up all timer failed");
518 
519 	qdf_mem_free(ser_soc_obj->timers);
520 	ser_soc_obj->timers = NULL;
521 	ser_soc_obj->max_active_cmds = 0;
522 
523 	wlan_serialization_destroy_lock(&ser_soc_obj->timer_lock);
524 error:
525 	ser_exit();
526 	return status;
527 }
528 
529 QDF_STATUS wlan_serialization_psoc_open(struct wlan_objmgr_psoc *psoc)
530 {
531 	uint8_t pdev_count;
532 	struct wlan_ser_psoc_obj *ser_soc_obj =
533 		wlan_serialization_get_psoc_obj(psoc);
534 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
535 
536 	if (!ser_soc_obj) {
537 		ser_err("invalid ser_soc_obj");
538 		goto error;
539 	}
540 
541 	pdev_count = wlan_psoc_get_pdev_count(psoc);
542 	ser_soc_obj->max_active_cmds = WLAN_SER_MAX_ACTIVE_SCAN_CMDS +
543 					(pdev_count * WLAN_SER_MAX_VDEVS);
544 
545 	ser_soc_obj->timers =
546 		qdf_mem_malloc(sizeof(struct wlan_serialization_timer) *
547 				ser_soc_obj->max_active_cmds);
548 	if (!ser_soc_obj->timers) {
549 		ser_alert("Mem alloc failed for ser timers");
550 		status = QDF_STATUS_E_NOMEM;
551 		goto error;
552 	}
553 
554 	wlan_serialization_create_lock(&ser_soc_obj->timer_lock);
555 	status = QDF_STATUS_SUCCESS;
556 
557 error:
558 	ser_exit();
559 	return status;
560 }
561 
562 /**
563  * wlan_serialization_psoc_create_handler() - PSOC obj create callback
564  * @psoc: PSOC object
565  * @arg_list: Variable argument list
566  *
567  * This callback is registered with object manager during initialization and
568  * when obj manager gets its turn to create the object, it would notify each
569  * component with the corresponding callback registered to inform the
570  * completion of the creation of the respective object.
571  *
572  * Return: QDF Status
573  */
574 static QDF_STATUS wlan_serialization_psoc_create_handler(
575 		struct wlan_objmgr_psoc *psoc, void *arg_list)
576 {
577 	struct wlan_ser_psoc_obj *soc_ser_obj;
578 	QDF_STATUS status = QDF_STATUS_E_NOMEM;
579 
580 	ser_enter();
581 
582 	soc_ser_obj =
583 		qdf_mem_malloc(sizeof(*soc_ser_obj));
584 	if (!soc_ser_obj) {
585 		ser_alert("Mem alloc failed for ser psoc priv obj");
586 		goto error;
587 	}
588 	wlan_objmgr_psoc_component_obj_attach(psoc,
589 					      WLAN_UMAC_COMP_SERIALIZATION,
590 					      soc_ser_obj,
591 					      QDF_STATUS_SUCCESS);
592 	ser_debug("ser psoc obj created");
593 
594 	status = QDF_STATUS_SUCCESS;
595 
596 error:
597 	ser_exit();
598 	return status;
599 }
600 
601 /**
602  * wlan_serialization_destroy_cmd_pool() - Destroy the global cmd pool
603  * @ser_pdev_obj: Serialization private pdev object
604  *
605  * Return: None
606  */
607 static void wlan_serialization_destroy_cmd_pool(
608 		struct wlan_serialization_pdev_queue *pdev_queue)
609 {
610 	qdf_list_node_t *node = NULL;
611 	struct wlan_serialization_command_list *cmd_list;
612 
613 	ser_enter();
614 	while (!qdf_list_empty(&pdev_queue->cmd_pool_list)) {
615 		qdf_list_remove_front(&pdev_queue->cmd_pool_list,
616 				      &node);
617 		cmd_list = (struct wlan_serialization_command_list *)node;
618 		ser_debug("Node being freed from global pool %pK",
619 			  cmd_list);
620 		qdf_mem_free(cmd_list);
621 	}
622 
623 	qdf_list_destroy(&pdev_queue->cmd_pool_list);
624 
625 	ser_exit();
626 }
627 
628 /**
629  * wlan_serialization_create_cmd_pool() - Create the global cmd pool
630  * @pdev: PDEV Object
631  * @ser_pdev_obj: Serialization private pdev object
632  *
633  * Global command pool of memory is created here.
634  * It is safe to allocate memory individually for each command rather than
635  * requesting for a huge chunk of memory at once.
636  *
637  * The individual command nodes allocated above will keep moving between
638  * the active, pending and global pool lists dynamically, but all the
639  * memory will be freed during driver unload only.
640  *
641  * Return: QDF Status
642  */
643 static QDF_STATUS
644 wlan_serialization_create_cmd_pool(
645 		struct wlan_serialization_pdev_queue *pdev_queue,
646 		uint16_t cmd_pool_size)
647 {
648 	struct wlan_serialization_command_list *cmd_list_ptr;
649 	uint8_t i;
650 	QDF_STATUS status = QDF_STATUS_E_NOMEM;
651 
652 	ser_enter();
653 
654 	for (i = 0; i < cmd_pool_size; i++) {
655 		cmd_list_ptr = qdf_mem_malloc(sizeof(*cmd_list_ptr));
656 		if (!cmd_list_ptr) {
657 			ser_alert("Mem alloc failed for cmd node");
658 			wlan_serialization_destroy_cmd_pool(pdev_queue);
659 			goto error;
660 		}
661 
662 		qdf_mem_zero(cmd_list_ptr, sizeof(*cmd_list_ptr));
663 		qdf_list_insert_back(
664 				     &pdev_queue->cmd_pool_list,
665 				     &cmd_list_ptr->pdev_node);
666 		cmd_list_ptr->cmd_in_use = 0;
667 		ser_debug("Created node at %pK and inserted to pool",
668 			  cmd_list_ptr);
669 	}
670 
671 	status = QDF_STATUS_SUCCESS;
672 
673 error:
674 	ser_exit();
675 	return status;
676 }
677 
678 /**
679  * wlan_serialization_pdev_create_handler() - PDEV obj create callback
680  * @pdev: PDEV object
681  * @arg_list: Variable argument list
682  *
683  * This callback is registered with object manager during initialization and
684  * when obj manager gets its turn to create the object, it would notify each
685  * component with the corresponding callback registered to inform the
686  * completion of the creation of the respective object.
687  *
688  * Return: QDF Status
689  */
690 static QDF_STATUS wlan_serialization_pdev_create_handler(
691 		struct wlan_objmgr_pdev *pdev, void *arg_list)
692 {
693 	struct wlan_ser_pdev_obj *ser_pdev_obj;
694 	struct wlan_serialization_pdev_queue *pdev_queue;
695 	QDF_STATUS status = QDF_STATUS_E_NOMEM;
696 	uint8_t index;
697 	uint8_t max_active_cmds;
698 	uint8_t max_pending_cmds;
699 	uint16_t cmd_pool_size;
700 
701 	ser_enter();
702 
703 	ser_pdev_obj =
704 		qdf_mem_malloc(sizeof(*ser_pdev_obj));
705 	if (!ser_pdev_obj) {
706 		ser_alert("Mem alloc failed for ser pdev obj");
707 		goto error;
708 	}
709 
710 	for (index = 0; index < SER_PDEV_QUEUE_COMP_MAX; index++) {
711 		pdev_queue = &ser_pdev_obj->pdev_q[index];
712 
713 		wlan_serialization_create_lock(&pdev_queue->pdev_queue_lock);
714 
715 		switch (index) {
716 		case SER_PDEV_QUEUE_COMP_SCAN:
717 			max_active_cmds = WLAN_SER_MAX_ACTIVE_SCAN_CMDS;
718 			max_pending_cmds = WLAN_SER_MAX_PENDING_SCAN_CMDS;
719 			cmd_pool_size = max_active_cmds + max_pending_cmds;
720 			break;
721 
722 		case SER_PDEV_QUEUE_COMP_NON_SCAN:
723 			max_active_cmds = WLAN_SER_MAX_ACTIVE_CMDS;
724 			max_pending_cmds = WLAN_SER_MAX_PENDING_CMDS;
725 			cmd_pool_size = max_active_cmds + max_pending_cmds;
726 			break;
727 		}
728 		qdf_list_create(&pdev_queue->active_list,
729 				max_active_cmds);
730 		qdf_list_create(&pdev_queue->pending_list,
731 				max_pending_cmds);
732 		qdf_list_create(&pdev_queue->cmd_pool_list,
733 				cmd_pool_size);
734 
735 		status = wlan_serialization_create_cmd_pool(pdev_queue,
736 							    cmd_pool_size);
737 		if (status != QDF_STATUS_SUCCESS) {
738 			ser_err("ser_pdev_obj failed status %d", status);
739 			goto error;
740 	}
741 
742 		pdev_queue->vdev_active_cmd_bitmap = 0;
743 		pdev_queue->blocking_cmd_active = 0;
744 		pdev_queue->blocking_cmd_waiting = 0;
745 	}
746 
747 	status = wlan_objmgr_pdev_component_obj_attach(
748 			pdev, WLAN_UMAC_COMP_SERIALIZATION,
749 			ser_pdev_obj, QDF_STATUS_SUCCESS);
750 
751 	if (status != QDF_STATUS_SUCCESS)
752 		ser_err("serialization pdev obj attach failed");
753 
754 error:
755 	ser_exit();
756 	return status;
757 }
758 
759 /**
760  * wlan_serialization_psoc_destroy_handler() - PSOC obj delete callback
761  * @psoc: PSOC object
762  * @arg_list: Variable argument list
763  *
764  * This callback is registered with object manager during initialization and
765  * when obj manager gets its turn to delete the object, it would notify each
766  * component with the corresponding callback registered to inform the
767  * completion of the deletion of the respective object.
768  *
769  * Return: QDF Status
770  */
771 static QDF_STATUS
772 wlan_serialization_psoc_destroy_handler(struct wlan_objmgr_psoc *psoc,
773 					void *arg_list)
774 {
775 	QDF_STATUS status = QDF_STATUS_E_FAULT;
776 	struct wlan_ser_psoc_obj *ser_soc_obj =
777 		wlan_serialization_get_psoc_obj(psoc);
778 
779 	ser_enter();
780 
781 	if (!ser_soc_obj) {
782 		ser_err("invalid ser_soc_obj");
783 		goto error;
784 	}
785 	status = wlan_objmgr_psoc_component_obj_detach(
786 			psoc, WLAN_UMAC_COMP_SERIALIZATION, ser_soc_obj);
787 	if (status != QDF_STATUS_SUCCESS)
788 		ser_err("ser psoc private obj detach failed");
789 
790 	ser_debug("ser psoc obj deleted with status %d", status);
791 	qdf_mem_free(ser_soc_obj);
792 
793 error:
794 	ser_exit();
795 	return status;
796 }
797 
798 /**
799  * wlan_serialization_pdev_destroy_handler() - PDEV obj delete callback
800  * @pdev: PDEV object
801  * @arg_list: Variable argument list
802  *
803  * This callback is registered with object manager during initialization and
804  * when obj manager gets its turn to delete the object, it would notify each
805  * component with the corresponding callback registered to inform the
806  * completion of the deletion of the respective object.
807  *
808  * Return: QDF Status
809  */
810 static QDF_STATUS wlan_serialization_pdev_destroy_handler(
811 		struct wlan_objmgr_pdev *pdev, void *arg_list)
812 {
813 	QDF_STATUS status;
814 	struct wlan_serialization_pdev_queue *pdev_queue;
815 	struct wlan_ser_pdev_obj *ser_pdev_obj =
816 		wlan_serialization_get_pdev_obj(pdev);
817 	uint8_t index;
818 
819 	ser_enter();
820 
821 	status = wlan_objmgr_pdev_component_obj_detach(
822 			pdev, WLAN_UMAC_COMP_SERIALIZATION, ser_pdev_obj);
823 
824 	for (index = 0; index < SER_PDEV_QUEUE_COMP_MAX; index++) {
825 		pdev_queue = &ser_pdev_obj->pdev_q[index];
826 
827 		wlan_serialization_destroy_pdev_list(pdev_queue);
828 		wlan_serialization_destroy_cmd_pool(pdev_queue);
829 
830 		wlan_serialization_destroy_lock(&pdev_queue->pdev_queue_lock);
831 	}
832 
833 	qdf_mem_free(ser_pdev_obj);
834 
835 	ser_exit();
836 	return status;
837 }
838 
839 /**
840  * wlan_serialization_vdev_create_handler() - VDEV obj create callback
841  * @vdev: VDEV object
842  * @arg_list: Variable argument list
843  *
844  * This callback is registered with object manager during initialization and
845  * when obj manager gets its turn to create the object, it would notify each
846  * component with the corresponding callback registered to inform the
847  * completion of the creation of the respective object.
848  *
849  * Return: QDF Status
850  */
851 static QDF_STATUS
852 wlan_serialization_vdev_create_handler(struct wlan_objmgr_vdev *vdev,
853 				       void *arg_list)
854 {
855 	struct wlan_ser_vdev_obj *ser_vdev_obj;
856 	struct wlan_serialization_vdev_queue *vdev_q;
857 	QDF_STATUS status = QDF_STATUS_E_NOMEM;
858 	uint8_t index;
859 	uint8_t max_active_cmds;
860 	uint8_t max_pending_cmds;
861 
862 	ser_enter();
863 
864 	ser_vdev_obj = qdf_mem_malloc(sizeof(*ser_vdev_obj));
865 	if (!ser_vdev_obj) {
866 		ser_alert("Mem alloc failed for ser vdev obj");
867 		goto error;
868 	}
869 
870 	for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) {
871 		vdev_q = &ser_vdev_obj->vdev_q[index];
872 
873 		switch (index) {
874 		case SER_VDEV_QUEUE_COMP_NON_SCAN:
875 			max_active_cmds = WLAN_SER_MAX_ACTIVE_CMDS /
876 				WLAN_SER_MAX_VDEVS;
877 			max_pending_cmds = WLAN_SER_MAX_PENDING_CMDS /
878 				WLAN_SER_MAX_VDEVS;
879 			break;
880 		}
881 
882 		qdf_list_create(&vdev_q->active_list,
883 				max_active_cmds);
884 		qdf_list_create(&vdev_q->pending_list,
885 				max_pending_cmds);
886 	}
887 
888 	status = wlan_objmgr_vdev_component_obj_attach(
889 			vdev, WLAN_UMAC_COMP_SERIALIZATION, ser_vdev_obj,
890 			QDF_STATUS_SUCCESS);
891 
892 	if (status != QDF_STATUS_SUCCESS)
893 		ser_err("serialization vdev obj attach failed");
894 
895 error:
896 	ser_exit();
897 	return status;
898 }
899 
900 /**
901  * wlan_serialization_vdev_destroy_handler() - vdev obj delete callback
902  * @vdev: VDEV object
903  * @arg_list: Variable argument list
904  *
905  * This callback is registered with object manager during initialization and
906  * when obj manager gets its turn to delete the object, it would notify each
907  * component with the corresponding callback registered to inform the
908  * completion of the deletion of the respective object.
909  *
910  * Return: QDF Status
911  */
912 static QDF_STATUS wlan_serialization_vdev_destroy_handler(
913 		struct wlan_objmgr_vdev *vdev, void *arg_list)
914 {
915 	QDF_STATUS status = QDF_STATUS_SUCCESS;
916 	struct wlan_serialization_vdev_queue *vdev_q;
917 	struct wlan_ser_vdev_obj *ser_vdev_obj =
918 		wlan_serialization_get_vdev_obj(vdev);
919 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
920 	uint8_t index;
921 
922 	ser_enter();
923 
924 	status = wlan_objmgr_vdev_component_obj_detach(
925 			vdev, WLAN_UMAC_COMP_SERIALIZATION, ser_vdev_obj);
926 
927 	for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) {
928 		vdev_q = &ser_vdev_obj->vdev_q[index];
929 		wlan_serialization_destroy_vdev_list(&vdev_q->active_list);
930 		wlan_serialization_destroy_vdev_list(&vdev_q->pending_list);
931 	}
932 
933 	qdf_mem_free(ser_vdev_obj);
934 	if (!ser_legacy_cb.serialization_purge_cmd_list)
935 		goto error;
936 
937 	ser_debug("for vdev_id[%d] vdev[%pK] flush all cmds",
938 		  vdev_id, vdev);
939 	ser_legacy_cb.serialization_purge_cmd_list(wlan_vdev_get_psoc(vdev),
940 						   vdev, false, false,
941 						   false, false, true);
942 
943 error:
944 	ser_exit();
945 	return status;
946 }
947 
948 QDF_STATUS wlan_serialization_init(void)
949 {
950 	QDF_STATUS status = QDF_STATUS_SUCCESS;
951 
952 	ser_enter();
953 
954 	status = wlan_objmgr_register_psoc_create_handler(
955 			WLAN_UMAC_COMP_SERIALIZATION,
956 			wlan_serialization_psoc_create_handler, NULL);
957 	if (status != QDF_STATUS_SUCCESS) {
958 		ser_err("Failed to reg soc ser obj create handler");
959 		goto err_psoc_create;
960 	}
961 
962 	status = wlan_objmgr_register_psoc_destroy_handler(
963 			WLAN_UMAC_COMP_SERIALIZATION,
964 			wlan_serialization_psoc_destroy_handler, NULL);
965 	if (status != QDF_STATUS_SUCCESS) {
966 		ser_err("Failed to reg soc ser obj delete handler");
967 		goto err_psoc_delete;
968 	}
969 
970 	status = wlan_objmgr_register_pdev_create_handler(
971 			WLAN_UMAC_COMP_SERIALIZATION,
972 			wlan_serialization_pdev_create_handler, NULL);
973 	if (status != QDF_STATUS_SUCCESS) {
974 		ser_err("Failed to reg pdev ser obj create handler");
975 		goto err_pdev_create;
976 	}
977 
978 	status = wlan_objmgr_register_pdev_destroy_handler(
979 			WLAN_UMAC_COMP_SERIALIZATION,
980 			wlan_serialization_pdev_destroy_handler, NULL);
981 	if (status != QDF_STATUS_SUCCESS) {
982 		ser_err("Failed to reg pdev ser obj delete handler");
983 		goto err_pdev_delete;
984 	}
985 
986 	status = wlan_objmgr_register_vdev_create_handler(
987 			WLAN_UMAC_COMP_SERIALIZATION,
988 			wlan_serialization_vdev_create_handler, NULL);
989 	if (status != QDF_STATUS_SUCCESS) {
990 		ser_err("Failed to reg vdev ser obj create handler");
991 		goto err_vdev_create;
992 	}
993 
994 	status = wlan_objmgr_register_vdev_destroy_handler(
995 			WLAN_UMAC_COMP_SERIALIZATION,
996 			wlan_serialization_vdev_destroy_handler, NULL);
997 	if (status != QDF_STATUS_SUCCESS) {
998 		ser_err("Failed to reg vdev ser obj delete handler");
999 		goto err_vdev_delete;
1000 	}
1001 	ser_debug("serialization handlers registered with obj mgr");
1002 	/*
1003 	 * Initialize the structure so all callbacks are registered
1004 	 * initially as NULL.
1005 	 */
1006 	qdf_mem_zero(&ser_legacy_cb, sizeof(ser_legacy_cb));
1007 
1008 	status = QDF_STATUS_SUCCESS;
1009 	goto exit;
1010 
1011 err_vdev_delete:
1012 	wlan_objmgr_unregister_vdev_create_handler(
1013 			WLAN_UMAC_COMP_SERIALIZATION,
1014 			wlan_serialization_vdev_create_handler,
1015 			NULL);
1016 err_vdev_create:
1017 	wlan_objmgr_unregister_pdev_destroy_handler(
1018 			WLAN_UMAC_COMP_SERIALIZATION,
1019 			wlan_serialization_pdev_destroy_handler,
1020 			NULL);
1021 err_pdev_delete:
1022 	wlan_objmgr_unregister_pdev_create_handler(
1023 			WLAN_UMAC_COMP_SERIALIZATION,
1024 			wlan_serialization_pdev_create_handler,
1025 			NULL);
1026 err_pdev_create:
1027 	wlan_objmgr_unregister_psoc_destroy_handler(
1028 			WLAN_UMAC_COMP_SERIALIZATION,
1029 			wlan_serialization_psoc_destroy_handler,
1030 			NULL);
1031 err_psoc_delete:
1032 	wlan_objmgr_unregister_psoc_create_handler(
1033 			WLAN_UMAC_COMP_SERIALIZATION,
1034 			wlan_serialization_psoc_create_handler,
1035 			NULL);
1036 err_psoc_create:
1037 exit:
1038 	ser_exit();
1039 	return status;
1040 }
1041 
1042 QDF_STATUS wlan_serialization_deinit(void)
1043 {
1044 	QDF_STATUS status;
1045 	QDF_STATUS ret_status = QDF_STATUS_SUCCESS;
1046 
1047 	ser_enter();
1048 
1049 	status = wlan_objmgr_unregister_psoc_create_handler(
1050 			WLAN_UMAC_COMP_SERIALIZATION,
1051 			wlan_serialization_psoc_create_handler,
1052 			NULL);
1053 
1054 	if (status != QDF_STATUS_SUCCESS) {
1055 		ser_err("unreg fail for psoc ser obj create notf:%d", status);
1056 		ret_status = QDF_STATUS_E_FAILURE;
1057 	}
1058 	status = wlan_objmgr_unregister_psoc_destroy_handler(
1059 			WLAN_UMAC_COMP_SERIALIZATION,
1060 			wlan_serialization_psoc_destroy_handler,
1061 			NULL);
1062 
1063 	if (status != QDF_STATUS_SUCCESS) {
1064 		ser_err("unreg fail for psoc ser obj destroy notf:%d", status);
1065 		ret_status = QDF_STATUS_E_FAILURE;
1066 	}
1067 
1068 	status = wlan_objmgr_unregister_pdev_create_handler(
1069 			WLAN_UMAC_COMP_SERIALIZATION,
1070 			wlan_serialization_pdev_create_handler,
1071 			NULL);
1072 	if (status != QDF_STATUS_SUCCESS) {
1073 		ser_err("unreg fail for pdev ser obj create notf:%d", status);
1074 		ret_status = QDF_STATUS_E_FAILURE;
1075 	}
1076 
1077 	status = wlan_objmgr_unregister_pdev_destroy_handler(
1078 			WLAN_UMAC_COMP_SERIALIZATION,
1079 			wlan_serialization_pdev_destroy_handler,
1080 			NULL);
1081 
1082 	if (status != QDF_STATUS_SUCCESS) {
1083 		ser_err("unreg fail for pdev ser destroy notf:%d", status);
1084 		ret_status = QDF_STATUS_E_FAILURE;
1085 	}
1086 
1087 	ser_alert("deregistered callbacks with obj mgr successfully");
1088 	/*
1089 	 * Initialize the structure so all callbacks are registered
1090 	 * initially as NULL.
1091 	 */
1092 	qdf_mem_zero(&ser_legacy_cb, sizeof(ser_legacy_cb));
1093 
1094 	ser_exit();
1095 	return ret_status;
1096 }
1097 #endif
1098