xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_main.c (revision 302a1d9701784af5f4797b1a9fe07ae820b51907)
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 error:
524 	ser_exit();
525 	return status;
526 }
527 
528 QDF_STATUS wlan_serialization_psoc_open(struct wlan_objmgr_psoc *psoc)
529 {
530 	uint8_t pdev_count;
531 	struct wlan_ser_psoc_obj *ser_soc_obj =
532 		wlan_serialization_get_psoc_obj(psoc);
533 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
534 
535 	if (!ser_soc_obj) {
536 		ser_err("invalid ser_soc_obj");
537 		goto error;
538 	}
539 
540 	pdev_count = wlan_psoc_get_pdev_count(psoc);
541 	ser_soc_obj->max_active_cmds = WLAN_SER_MAX_ACTIVE_SCAN_CMDS +
542 					(pdev_count * WLAN_SER_MAX_VDEVS);
543 
544 	ser_soc_obj->timers =
545 		qdf_mem_malloc(sizeof(struct wlan_serialization_timer) *
546 				ser_soc_obj->max_active_cmds);
547 	if (!ser_soc_obj->timers) {
548 		ser_alert("Mem alloc failed for ser timers");
549 		status = QDF_STATUS_E_NOMEM;
550 		goto error;
551 	}
552 
553 	status = QDF_STATUS_SUCCESS;
554 
555 error:
556 	ser_exit();
557 	return status;
558 }
559 
560 /**
561  * wlan_serialization_psoc_create_handler() - PSOC obj create callback
562  * @psoc: PSOC object
563  * @arg_list: Variable argument list
564  *
565  * This callback is registered with object manager during initialization and
566  * when obj manager gets its turn to create the object, it would notify each
567  * component with the corresponding callback registered to inform the
568  * completion of the creation of the respective object.
569  *
570  * Return: QDF Status
571  */
572 static QDF_STATUS wlan_serialization_psoc_create_handler(
573 		struct wlan_objmgr_psoc *psoc, void *arg_list)
574 {
575 	struct wlan_ser_psoc_obj *soc_ser_obj;
576 	QDF_STATUS status = QDF_STATUS_E_NOMEM;
577 
578 	ser_enter();
579 
580 	soc_ser_obj =
581 		qdf_mem_malloc(sizeof(*soc_ser_obj));
582 	if (!soc_ser_obj) {
583 		ser_alert("Mem alloc failed for ser psoc priv obj");
584 		goto error;
585 	}
586 	wlan_objmgr_psoc_component_obj_attach(psoc,
587 					      WLAN_UMAC_COMP_SERIALIZATION,
588 					      soc_ser_obj,
589 					      QDF_STATUS_SUCCESS);
590 	ser_debug("ser psoc obj created");
591 
592 	status = QDF_STATUS_SUCCESS;
593 
594 error:
595 	ser_exit();
596 	return status;
597 }
598 
599 /**
600  * wlan_serialization_destroy_cmd_pool() - Destroy the global cmd pool
601  * @ser_pdev_obj: Serialization private pdev object
602  *
603  * Return: None
604  */
605 static void wlan_serialization_destroy_cmd_pool(
606 		struct wlan_serialization_pdev_queue *pdev_queue)
607 {
608 	qdf_list_node_t *node = NULL;
609 	struct wlan_serialization_command_list *cmd_list;
610 
611 	ser_enter();
612 	while (!qdf_list_empty(&pdev_queue->cmd_pool_list)) {
613 		qdf_list_remove_front(&pdev_queue->cmd_pool_list,
614 				      &node);
615 		cmd_list = (struct wlan_serialization_command_list *)node;
616 		ser_debug("Node being freed from global pool %pK",
617 			  cmd_list);
618 		qdf_mem_free(cmd_list);
619 	}
620 
621 	qdf_list_destroy(&pdev_queue->cmd_pool_list);
622 
623 	ser_exit();
624 }
625 
626 /**
627  * wlan_serialization_create_cmd_pool() - Create the global cmd pool
628  * @pdev: PDEV Object
629  * @ser_pdev_obj: Serialization private pdev object
630  *
631  * Global command pool of memory is created here.
632  * It is safe to allocate memory individually for each command rather than
633  * requesting for a huge chunk of memory at once.
634  *
635  * The individual command nodes allocated above will keep moving between
636  * the active, pending and global pool lists dynamically, but all the
637  * memory will be freed during driver unload only.
638  *
639  * Return: QDF Status
640  */
641 static QDF_STATUS
642 wlan_serialization_create_cmd_pool(
643 		struct wlan_serialization_pdev_queue *pdev_queue,
644 		uint16_t cmd_pool_size)
645 {
646 	struct wlan_serialization_command_list *cmd_list_ptr;
647 	uint8_t i;
648 	QDF_STATUS status = QDF_STATUS_E_NOMEM;
649 
650 	ser_enter();
651 
652 	for (i = 0; i < cmd_pool_size; i++) {
653 		cmd_list_ptr = qdf_mem_malloc(sizeof(*cmd_list_ptr));
654 		if (!cmd_list_ptr) {
655 			ser_alert("Mem alloc failed for cmd node");
656 			wlan_serialization_destroy_cmd_pool(pdev_queue);
657 			goto error;
658 		}
659 
660 		qdf_mem_zero(cmd_list_ptr, sizeof(*cmd_list_ptr));
661 		qdf_list_insert_back(
662 				     &pdev_queue->cmd_pool_list,
663 				     &cmd_list_ptr->pdev_node);
664 		cmd_list_ptr->cmd_in_use = 0;
665 		ser_debug("Created node at %pK and inserted to pool",
666 			  cmd_list_ptr);
667 	}
668 
669 	status = QDF_STATUS_SUCCESS;
670 
671 error:
672 	ser_exit();
673 	return status;
674 }
675 
676 /**
677  * wlan_serialization_pdev_create_handler() - PDEV obj create callback
678  * @pdev: PDEV object
679  * @arg_list: Variable argument list
680  *
681  * This callback is registered with object manager during initialization and
682  * when obj manager gets its turn to create the object, it would notify each
683  * component with the corresponding callback registered to inform the
684  * completion of the creation of the respective object.
685  *
686  * Return: QDF Status
687  */
688 static QDF_STATUS wlan_serialization_pdev_create_handler(
689 		struct wlan_objmgr_pdev *pdev, void *arg_list)
690 {
691 	struct wlan_ser_pdev_obj *ser_pdev_obj;
692 	struct wlan_serialization_pdev_queue *pdev_queue;
693 	QDF_STATUS status = QDF_STATUS_E_NOMEM;
694 	uint8_t index;
695 	uint8_t max_active_cmds;
696 	uint8_t max_pending_cmds;
697 	uint16_t cmd_pool_size;
698 
699 	ser_enter();
700 
701 	ser_pdev_obj =
702 		qdf_mem_malloc(sizeof(*ser_pdev_obj));
703 	if (!ser_pdev_obj) {
704 		ser_alert("Mem alloc failed for ser pdev obj");
705 		goto error;
706 	}
707 
708 	for (index = 0; index < SER_PDEV_QUEUE_COMP_MAX; index++) {
709 		pdev_queue = &ser_pdev_obj->pdev_q[index];
710 
711 		qdf_spinlock_create(&pdev_queue->pdev_queue_lock);
712 
713 		switch (index) {
714 		case SER_PDEV_QUEUE_COMP_SCAN:
715 			max_active_cmds = WLAN_SER_MAX_ACTIVE_SCAN_CMDS;
716 			max_pending_cmds = WLAN_SER_MAX_PENDING_SCAN_CMDS;
717 			cmd_pool_size = max_active_cmds + max_pending_cmds;
718 			break;
719 
720 		case SER_PDEV_QUEUE_COMP_NON_SCAN:
721 			max_active_cmds = WLAN_SER_MAX_ACTIVE_CMDS;
722 			max_pending_cmds = WLAN_SER_MAX_PENDING_CMDS;
723 			cmd_pool_size = max_active_cmds + max_pending_cmds;
724 			break;
725 		}
726 		qdf_list_create(&pdev_queue->active_list,
727 				max_active_cmds);
728 		qdf_list_create(&pdev_queue->pending_list,
729 				max_pending_cmds);
730 		qdf_list_create(&pdev_queue->cmd_pool_list,
731 				cmd_pool_size);
732 
733 		status = wlan_serialization_create_cmd_pool(pdev_queue,
734 							    cmd_pool_size);
735 		if (status != QDF_STATUS_SUCCESS) {
736 			ser_err("ser_pdev_obj failed status %d", status);
737 			goto error;
738 	}
739 
740 		pdev_queue->vdev_active_cmd_bitmap = 0;
741 		pdev_queue->blocking_cmd_active = 0;
742 		pdev_queue->blocking_cmd_waiting = 0;
743 	}
744 
745 	status = wlan_objmgr_pdev_component_obj_attach(
746 			pdev, WLAN_UMAC_COMP_SERIALIZATION,
747 			ser_pdev_obj, QDF_STATUS_SUCCESS);
748 
749 	if (status != QDF_STATUS_SUCCESS)
750 		ser_err("serialization pdev obj attach failed");
751 
752 error:
753 	ser_exit();
754 	return status;
755 }
756 
757 /**
758  * wlan_serialization_psoc_destroy_handler() - PSOC obj delete callback
759  * @psoc: PSOC object
760  * @arg_list: Variable argument list
761  *
762  * This callback is registered with object manager during initialization and
763  * when obj manager gets its turn to delete the object, it would notify each
764  * component with the corresponding callback registered to inform the
765  * completion of the deletion of the respective object.
766  *
767  * Return: QDF Status
768  */
769 static QDF_STATUS
770 wlan_serialization_psoc_destroy_handler(struct wlan_objmgr_psoc *psoc,
771 					void *arg_list)
772 {
773 	QDF_STATUS status = QDF_STATUS_E_FAULT;
774 	struct wlan_ser_psoc_obj *ser_soc_obj =
775 		wlan_serialization_get_psoc_obj(psoc);
776 
777 	ser_enter();
778 
779 	if (!ser_soc_obj) {
780 		ser_err("invalid ser_soc_obj");
781 		goto error;
782 	}
783 	status = wlan_objmgr_psoc_component_obj_detach(
784 			psoc, WLAN_UMAC_COMP_SERIALIZATION, ser_soc_obj);
785 	if (status != QDF_STATUS_SUCCESS)
786 		ser_err("ser psoc private obj detach failed");
787 
788 	ser_debug("ser psoc obj deleted with status %d", status);
789 	qdf_mem_free(ser_soc_obj);
790 
791 error:
792 	ser_exit();
793 	return status;
794 }
795 
796 /**
797  * wlan_serialization_pdev_destroy_handler() - PDEV obj delete callback
798  * @pdev: PDEV object
799  * @arg_list: Variable argument list
800  *
801  * This callback is registered with object manager during initialization and
802  * when obj manager gets its turn to delete the object, it would notify each
803  * component with the corresponding callback registered to inform the
804  * completion of the deletion of the respective object.
805  *
806  * Return: QDF Status
807  */
808 static QDF_STATUS wlan_serialization_pdev_destroy_handler(
809 		struct wlan_objmgr_pdev *pdev, void *arg_list)
810 {
811 	QDF_STATUS status;
812 	struct wlan_serialization_pdev_queue *pdev_queue;
813 	struct wlan_ser_pdev_obj *ser_pdev_obj =
814 		wlan_serialization_get_pdev_obj(pdev);
815 	uint8_t index;
816 
817 	ser_enter();
818 
819 	status = wlan_objmgr_pdev_component_obj_detach(
820 			pdev, WLAN_UMAC_COMP_SERIALIZATION, ser_pdev_obj);
821 
822 	for (index = 0; index < SER_PDEV_QUEUE_COMP_MAX; index++) {
823 		pdev_queue = &ser_pdev_obj->pdev_q[index];
824 
825 		wlan_serialization_destroy_pdev_list(pdev_queue);
826 		wlan_serialization_destroy_cmd_pool(pdev_queue);
827 
828 		qdf_spinlock_destroy(&pdev_queue->pdev_queue_lock);
829 	}
830 
831 	qdf_mem_free(ser_pdev_obj);
832 
833 	ser_exit();
834 	return status;
835 }
836 
837 /**
838  * wlan_serialization_vdev_create_handler() - VDEV obj create callback
839  * @vdev: VDEV object
840  * @arg_list: Variable argument list
841  *
842  * This callback is registered with object manager during initialization and
843  * when obj manager gets its turn to create the object, it would notify each
844  * component with the corresponding callback registered to inform the
845  * completion of the creation of the respective object.
846  *
847  * Return: QDF Status
848  */
849 static QDF_STATUS
850 wlan_serialization_vdev_create_handler(struct wlan_objmgr_vdev *vdev,
851 				       void *arg_list)
852 {
853 	struct wlan_ser_vdev_obj *ser_vdev_obj;
854 	struct wlan_serialization_vdev_queue *vdev_q;
855 	QDF_STATUS status = QDF_STATUS_E_NOMEM;
856 	uint8_t index;
857 	uint8_t max_active_cmds;
858 	uint8_t max_pending_cmds;
859 
860 	ser_enter();
861 
862 	ser_vdev_obj = qdf_mem_malloc(sizeof(*ser_vdev_obj));
863 	if (!ser_vdev_obj) {
864 		ser_alert("Mem alloc failed for ser vdev obj");
865 		goto error;
866 	}
867 
868 	for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) {
869 		vdev_q = &ser_vdev_obj->vdev_q[index];
870 
871 		switch (index) {
872 		case SER_VDEV_QUEUE_COMP_NON_SCAN:
873 			max_active_cmds = WLAN_SER_MAX_ACTIVE_CMDS /
874 				WLAN_SER_MAX_VDEVS;
875 			max_pending_cmds = WLAN_SER_MAX_PENDING_CMDS /
876 				WLAN_SER_MAX_VDEVS;
877 			break;
878 		}
879 
880 		qdf_list_create(&vdev_q->active_list,
881 				max_active_cmds);
882 		qdf_list_create(&vdev_q->pending_list,
883 				max_pending_cmds);
884 	}
885 
886 	status = wlan_objmgr_vdev_component_obj_attach(
887 			vdev, WLAN_UMAC_COMP_SERIALIZATION, ser_vdev_obj,
888 			QDF_STATUS_SUCCESS);
889 
890 	if (status != QDF_STATUS_SUCCESS)
891 		ser_err("serialization vdev obj attach failed");
892 
893 error:
894 	ser_exit();
895 	return status;
896 }
897 
898 /**
899  * wlan_serialization_vdev_destroy_handler() - vdev obj delete callback
900  * @vdev: VDEV object
901  * @arg_list: Variable argument list
902  *
903  * This callback is registered with object manager during initialization and
904  * when obj manager gets its turn to delete the object, it would notify each
905  * component with the corresponding callback registered to inform the
906  * completion of the deletion of the respective object.
907  *
908  * Return: QDF Status
909  */
910 static QDF_STATUS wlan_serialization_vdev_destroy_handler(
911 		struct wlan_objmgr_vdev *vdev, void *arg_list)
912 {
913 	QDF_STATUS status = QDF_STATUS_SUCCESS;
914 	struct wlan_serialization_vdev_queue *vdev_q;
915 	struct wlan_ser_vdev_obj *ser_vdev_obj =
916 		wlan_serialization_get_vdev_obj(vdev);
917 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
918 	uint8_t index;
919 
920 	ser_enter();
921 
922 	status = wlan_objmgr_vdev_component_obj_detach(
923 			vdev, WLAN_UMAC_COMP_SERIALIZATION, ser_vdev_obj);
924 
925 	for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) {
926 		vdev_q = &ser_vdev_obj->vdev_q[index];
927 		wlan_serialization_destroy_vdev_list(&vdev_q->active_list);
928 		wlan_serialization_destroy_vdev_list(&vdev_q->pending_list);
929 	}
930 
931 	qdf_mem_free(ser_vdev_obj);
932 	if (!ser_legacy_cb.serialization_purge_cmd_list)
933 		goto error;
934 
935 	ser_debug("for vdev_id[%d] vdev[%pK] flush all cmds",
936 		  vdev_id, vdev);
937 	ser_legacy_cb.serialization_purge_cmd_list(wlan_vdev_get_psoc(vdev),
938 						   vdev, false, false,
939 						   false, false, true);
940 
941 error:
942 	ser_exit();
943 	return status;
944 }
945 
946 QDF_STATUS wlan_serialization_init(void)
947 {
948 	QDF_STATUS status = QDF_STATUS_SUCCESS;
949 
950 	ser_enter();
951 
952 	status = wlan_objmgr_register_psoc_create_handler(
953 			WLAN_UMAC_COMP_SERIALIZATION,
954 			wlan_serialization_psoc_create_handler, NULL);
955 	if (status != QDF_STATUS_SUCCESS) {
956 		ser_err("Failed to reg soc ser obj create handler");
957 		goto err_psoc_create;
958 	}
959 
960 	status = wlan_objmgr_register_psoc_destroy_handler(
961 			WLAN_UMAC_COMP_SERIALIZATION,
962 			wlan_serialization_psoc_destroy_handler, NULL);
963 	if (status != QDF_STATUS_SUCCESS) {
964 		ser_err("Failed to reg soc ser obj delete handler");
965 		goto err_psoc_delete;
966 	}
967 
968 	status = wlan_objmgr_register_pdev_create_handler(
969 			WLAN_UMAC_COMP_SERIALIZATION,
970 			wlan_serialization_pdev_create_handler, NULL);
971 	if (status != QDF_STATUS_SUCCESS) {
972 		ser_err("Failed to reg pdev ser obj create handler");
973 		goto err_pdev_create;
974 	}
975 
976 	status = wlan_objmgr_register_pdev_destroy_handler(
977 			WLAN_UMAC_COMP_SERIALIZATION,
978 			wlan_serialization_pdev_destroy_handler, NULL);
979 	if (status != QDF_STATUS_SUCCESS) {
980 		ser_err("Failed to reg pdev ser obj delete handler");
981 		goto err_pdev_delete;
982 	}
983 
984 	status = wlan_objmgr_register_vdev_create_handler(
985 			WLAN_UMAC_COMP_SERIALIZATION,
986 			wlan_serialization_vdev_create_handler, NULL);
987 	if (status != QDF_STATUS_SUCCESS) {
988 		ser_err("Failed to reg vdev ser obj create handler");
989 		goto err_vdev_create;
990 	}
991 
992 	status = wlan_objmgr_register_vdev_destroy_handler(
993 			WLAN_UMAC_COMP_SERIALIZATION,
994 			wlan_serialization_vdev_destroy_handler, NULL);
995 	if (status != QDF_STATUS_SUCCESS) {
996 		ser_err("Failed to reg vdev ser obj delete handler");
997 		goto err_vdev_delete;
998 	}
999 	ser_debug("serialization handlers registered with obj mgr");
1000 	/*
1001 	 * Initialize the structure so all callbacks are registered
1002 	 * initially as NULL.
1003 	 */
1004 	qdf_mem_zero(&ser_legacy_cb, sizeof(ser_legacy_cb));
1005 
1006 	status = QDF_STATUS_SUCCESS;
1007 	goto exit;
1008 
1009 err_vdev_delete:
1010 	wlan_objmgr_unregister_vdev_create_handler(
1011 			WLAN_UMAC_COMP_SERIALIZATION,
1012 			wlan_serialization_vdev_create_handler,
1013 			NULL);
1014 err_vdev_create:
1015 	wlan_objmgr_unregister_pdev_destroy_handler(
1016 			WLAN_UMAC_COMP_SERIALIZATION,
1017 			wlan_serialization_pdev_destroy_handler,
1018 			NULL);
1019 err_pdev_delete:
1020 	wlan_objmgr_unregister_pdev_create_handler(
1021 			WLAN_UMAC_COMP_SERIALIZATION,
1022 			wlan_serialization_pdev_create_handler,
1023 			NULL);
1024 err_pdev_create:
1025 	wlan_objmgr_unregister_psoc_destroy_handler(
1026 			WLAN_UMAC_COMP_SERIALIZATION,
1027 			wlan_serialization_psoc_destroy_handler,
1028 			NULL);
1029 err_psoc_delete:
1030 	wlan_objmgr_unregister_psoc_create_handler(
1031 			WLAN_UMAC_COMP_SERIALIZATION,
1032 			wlan_serialization_psoc_create_handler,
1033 			NULL);
1034 err_psoc_create:
1035 exit:
1036 	ser_exit();
1037 	return status;
1038 }
1039 
1040 QDF_STATUS wlan_serialization_deinit(void)
1041 {
1042 	QDF_STATUS status;
1043 	QDF_STATUS ret_status = QDF_STATUS_SUCCESS;
1044 
1045 	ser_enter();
1046 
1047 	status = wlan_objmgr_unregister_psoc_create_handler(
1048 			WLAN_UMAC_COMP_SERIALIZATION,
1049 			wlan_serialization_psoc_create_handler,
1050 			NULL);
1051 
1052 	if (status != QDF_STATUS_SUCCESS) {
1053 		ser_err("unreg fail for psoc ser obj create notf:%d", status);
1054 		ret_status = QDF_STATUS_E_FAILURE;
1055 	}
1056 	status = wlan_objmgr_unregister_psoc_destroy_handler(
1057 			WLAN_UMAC_COMP_SERIALIZATION,
1058 			wlan_serialization_psoc_destroy_handler,
1059 			NULL);
1060 
1061 	if (status != QDF_STATUS_SUCCESS) {
1062 		ser_err("unreg fail for psoc ser obj destroy notf:%d", status);
1063 		ret_status = QDF_STATUS_E_FAILURE;
1064 	}
1065 
1066 	status = wlan_objmgr_unregister_pdev_create_handler(
1067 			WLAN_UMAC_COMP_SERIALIZATION,
1068 			wlan_serialization_pdev_create_handler,
1069 			NULL);
1070 	if (status != QDF_STATUS_SUCCESS) {
1071 		ser_err("unreg fail for pdev ser obj create notf:%d", status);
1072 		ret_status = QDF_STATUS_E_FAILURE;
1073 	}
1074 
1075 	status = wlan_objmgr_unregister_pdev_destroy_handler(
1076 			WLAN_UMAC_COMP_SERIALIZATION,
1077 			wlan_serialization_pdev_destroy_handler,
1078 			NULL);
1079 
1080 	if (status != QDF_STATUS_SUCCESS) {
1081 		ser_err("unreg fail for pdev ser destroy notf:%d", status);
1082 		ret_status = QDF_STATUS_E_FAILURE;
1083 	}
1084 
1085 	ser_alert("deregistered callbacks with obj mgr successfully");
1086 	/*
1087 	 * Initialize the structure so all callbacks are registered
1088 	 * initially as NULL.
1089 	 */
1090 	qdf_mem_zero(&ser_legacy_cb, sizeof(ser_legacy_cb));
1091 
1092 	ser_exit();
1093 	return ret_status;
1094 }
1095 #endif
1096