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