xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_main.c (revision a175314c51a4ce5cec2835cc8a8c7dc0c1810915)
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 #include "qdf_status.h"
26 #include "qdf_list.h"
27 #include "wlan_objmgr_cmn.h"
28 #include "wlan_objmgr_global_obj.h"
29 #include "wlan_objmgr_psoc_obj.h"
30 #include "wlan_serialization_main_i.h"
31 #include "wlan_serialization_rules_i.h"
32 #include "wlan_serialization_utils_i.h"
33 
34 struct serialization_legacy_callback ser_legacy_cb;
35 
36 QDF_STATUS wlan_serialization_psoc_close(struct wlan_objmgr_psoc *psoc)
37 {
38 	QDF_STATUS status;
39 	struct wlan_serialization_psoc_priv_obj *ser_soc_obj =
40 		wlan_serialization_get_psoc_priv_obj(psoc);
41 
42 	if (!ser_soc_obj) {
43 		serialization_err("invalid ser_soc_obj");
44 		return QDF_STATUS_E_FAILURE;
45 	}
46 	/* clean up all timers before exiting */
47 	status = wlan_serialization_cleanup_all_timers(ser_soc_obj);
48 	if (status != QDF_STATUS_SUCCESS)
49 		serialization_err("ser cleanning up all timer failed");
50 
51 	qdf_mem_free(ser_soc_obj->timers);
52 	ser_soc_obj->timers = NULL;
53 	ser_soc_obj->max_active_cmds = 0;
54 
55 	return status;
56 }
57 
58 QDF_STATUS wlan_serialization_psoc_open(struct wlan_objmgr_psoc *psoc)
59 {
60 	uint8_t pdev_count;
61 	struct wlan_serialization_psoc_priv_obj *ser_soc_obj =
62 		wlan_serialization_get_psoc_priv_obj(psoc);
63 
64 	if (!ser_soc_obj) {
65 		serialization_err("invalid ser_soc_obj");
66 		return QDF_STATUS_E_FAILURE;
67 	}
68 	/* TODO:Get WLAN_SERIALIZATION_MAX_ACTIVE_SCAN_CMDS frm service ready */
69 	pdev_count = wlan_psoc_get_pdev_count(psoc);
70 	ser_soc_obj->max_active_cmds = WLAN_SERIALIZATION_MAX_ACTIVE_SCAN_CMDS +
71 		pdev_count;
72 	ser_soc_obj->timers =
73 		qdf_mem_malloc(sizeof(struct wlan_serialization_timer) *
74 				ser_soc_obj->max_active_cmds);
75 	if (NULL == ser_soc_obj->timers) {
76 		serialization_alert("Mem alloc failed for ser timers");
77 		return QDF_STATUS_E_NOMEM;
78 	}
79 
80 	return QDF_STATUS_SUCCESS;
81 }
82 
83 /**
84  * wlan_serialization_psoc_obj_create_notification() - PSOC obj create callback
85  * @psoc: PSOC object
86  * @arg_list: Variable argument list
87  *
88  * This callback is registered with object manager during initialization and
89  * when obj manager gets its turn to create the object, it would notify each
90  * component with the corresponding callback registered to inform the
91  * completion of the creation of the respective object.
92  *
93  * Return: QDF Status
94  */
95 static QDF_STATUS wlan_serialization_psoc_obj_create_notification(
96 		struct wlan_objmgr_psoc *psoc, void *arg_list)
97 {
98 	struct wlan_serialization_psoc_priv_obj *soc_ser_obj;
99 
100 	soc_ser_obj =
101 		qdf_mem_malloc(sizeof(*soc_ser_obj));
102 	if (NULL == soc_ser_obj) {
103 		serialization_alert("Mem alloc failed for ser psoc priv obj");
104 		return QDF_STATUS_E_NOMEM;
105 	}
106 	wlan_objmgr_psoc_component_obj_attach(psoc,
107 			WLAN_UMAC_COMP_SERIALIZATION, soc_ser_obj,
108 			QDF_STATUS_SUCCESS);
109 	serialization_debug("ser psoc obj created");
110 
111 	return QDF_STATUS_SUCCESS;
112 }
113 
114 /**
115  * wlan_serialization_destroy_cmd_pool() - Destroy the global cmd pool
116  * @ser_pdev_obj: Serialization private pdev object
117  *
118  * Return: None
119  */
120 static void wlan_serialization_destroy_cmd_pool(
121 		  struct wlan_serialization_pdev_priv_obj *ser_pdev_obj)
122 {
123 
124 	qdf_list_node_t *node = NULL;
125 	struct wlan_serialization_command_list *cmd_list;
126 
127 	while (!qdf_list_empty(&ser_pdev_obj->global_cmd_pool_list)) {
128 		qdf_list_remove_front(&ser_pdev_obj->global_cmd_pool_list,
129 				&node);
130 		cmd_list = (struct wlan_serialization_command_list *)node;
131 		serialization_debug("Node being freed from global pool %pK",
132 				cmd_list);
133 		qdf_mem_free(cmd_list);
134 
135 	}
136 	qdf_list_destroy(&ser_pdev_obj->global_cmd_pool_list);
137 }
138 
139 /**
140  * wlan_serialization_create_cmd_pool() - Create the global cmd pool
141  * @pdev: PDEV Object
142  * @ser_pdev_obj: Serialization private pdev object
143  *
144  * Global command pool of memory is created here.
145  * It is safe to allocate memory individually for each command rather than
146  * requesting for a huge chunk of memory at once.
147  *
148  * The individual command nodes allocated above will keep moving between
149  * the active, pending and global pool lists dynamically, but all the
150  * memory will be freed during driver unload only.
151  *
152  * Return: QDF Status
153  */
154 static QDF_STATUS
155 wlan_serialization_create_cmd_pool(struct wlan_objmgr_pdev *pdev,
156 		struct wlan_serialization_pdev_priv_obj *ser_pdev_obj)
157 {
158 	struct wlan_serialization_command_list *cmd_list_ptr;
159 	uint8_t i;
160 
161 	for (i = 0; i < WLAN_SERIALIZATION_MAX_GLOBAL_POOL_CMDS; i++) {
162 		cmd_list_ptr = qdf_mem_malloc(sizeof(*cmd_list_ptr));
163 		if (NULL == cmd_list_ptr) {
164 			serialization_alert("Mem alloc failed for cmd node");
165 			wlan_serialization_destroy_cmd_pool(ser_pdev_obj);
166 			return QDF_STATUS_E_NOMEM;
167 		}
168 		qdf_list_insert_back(
169 				&ser_pdev_obj->global_cmd_pool_list,
170 				&cmd_list_ptr->node);
171 		cmd_list_ptr->cmd_in_use = 0;
172 		serialization_debug("Created node at %pK and inserted to pool",
173 				cmd_list_ptr);
174 	}
175 
176 	return QDF_STATUS_SUCCESS;
177 }
178 
179 
180 /**
181  * wlan_serialization_pdev_obj_create_notification() - PDEV obj create callback
182  * @pdev: PDEV object
183  * @arg_list: Variable argument list
184  *
185  * This callback is registered with object manager during initialization and
186  * when obj manager gets its turn to create the object, it would notify each
187  * component with the corresponding callback registered to inform the
188  * completion of the creation of the respective object.
189  *
190  * Return: QDF Status
191  */
192 static QDF_STATUS wlan_serialization_pdev_obj_create_notification(
193 		struct wlan_objmgr_pdev *pdev, void *arg_list)
194 {
195 	struct wlan_serialization_pdev_priv_obj *ser_pdev_obj;
196 	QDF_STATUS status;
197 
198 	ser_pdev_obj =
199 		qdf_mem_malloc(sizeof(*ser_pdev_obj));
200 	if (NULL == ser_pdev_obj) {
201 		serialization_alert("Mem alloc failed for ser pdev obj");
202 		return QDF_STATUS_E_NOMEM;
203 	}
204 	status = wlan_serialization_create_lock(ser_pdev_obj);
205 	if (status != QDF_STATUS_SUCCESS) {
206 		serialization_err("Failed to create serialization lock");
207 		return status;
208 	}
209 	qdf_list_create(&ser_pdev_obj->active_list,
210 			WLAN_SERIALIZATION_MAX_ACTIVE_CMDS);
211 	qdf_list_create(&ser_pdev_obj->pending_list,
212 			WLAN_SERIALIZATION_MAX_GLOBAL_POOL_CMDS);
213 	qdf_list_create(&ser_pdev_obj->active_scan_list,
214 			WLAN_SERIALIZATION_MAX_ACTIVE_SCAN_CMDS);
215 	qdf_list_create(&ser_pdev_obj->pending_scan_list,
216 			WLAN_SERIALIZATION_MAX_GLOBAL_POOL_CMDS);
217 	qdf_list_create(&ser_pdev_obj->global_cmd_pool_list,
218 			WLAN_SERIALIZATION_MAX_GLOBAL_POOL_CMDS);
219 	status = wlan_serialization_create_cmd_pool(pdev, ser_pdev_obj);
220 	if (status != QDF_STATUS_SUCCESS) {
221 		serialization_err("ser_pdev_obj failed status %d", status);
222 		return status;
223 	}
224 	status = wlan_objmgr_pdev_component_obj_attach(pdev,
225 		WLAN_UMAC_COMP_SERIALIZATION, ser_pdev_obj,
226 		QDF_STATUS_SUCCESS);
227 	if (status != QDF_STATUS_SUCCESS) {
228 		serialization_err("serialization pdev obj attach failed");
229 		return status;
230 	}
231 
232 	return status;
233 }
234 
235 /**
236  * wlan_serialization_psoc_obj_destroy_notification() - PSOC obj delete callback
237  * @psoc: PSOC object
238  * @arg_list: Variable argument list
239  *
240  * This callback is registered with object manager during initialization and
241  * when obj manager gets its turn to delete the object, it would notify each
242  * component with the corresponding callback registered to inform the
243  * completion of the deletion of the respective object.
244  *
245  * Return: QDF Status
246  */
247 static QDF_STATUS wlan_serialization_psoc_obj_destroy_notification(
248 		struct wlan_objmgr_psoc *psoc, void *arg_list)
249 {
250 	QDF_STATUS status;
251 	struct wlan_serialization_psoc_priv_obj *ser_soc_obj =
252 		wlan_serialization_get_psoc_priv_obj(psoc);
253 
254 	if (NULL == ser_soc_obj) {
255 		serialization_err("invalid ser_soc_obj");
256 		return QDF_STATUS_E_FAULT;
257 	}
258 	status = wlan_objmgr_psoc_component_obj_detach(psoc,
259 			WLAN_UMAC_COMP_SERIALIZATION,
260 			ser_soc_obj);
261 	if (status != QDF_STATUS_SUCCESS)
262 		serialization_err("ser psoc private obj detach failed");
263 	serialization_debug("ser psoc obj deleted with status %d", status);
264 	qdf_mem_free(ser_soc_obj);
265 
266 	return status;
267 }
268 
269 /**
270  * wlan_serialization_pdev_obj_destroy_notification() - PDEV obj delete callback
271  * @pdev: PDEV object
272  * @arg_list: Variable argument list
273  *
274  * This callback is registered with object manager during initialization and
275  * when obj manager gets its turn to delete the object, it would notify each
276  * component with the corresponding callback registered to inform the
277  * completion of the deletion of the respective object.
278  *
279  * Return: QDF Status
280  */
281 static QDF_STATUS wlan_serialization_pdev_obj_destroy_notification(
282 		struct wlan_objmgr_pdev *pdev, void *arg_list)
283 {
284 	QDF_STATUS status;
285 	struct wlan_serialization_pdev_priv_obj *ser_pdev_obj =
286 		wlan_serialization_get_pdev_priv_obj(pdev);
287 
288 	status = wlan_objmgr_pdev_component_obj_detach(pdev,
289 			WLAN_UMAC_COMP_SERIALIZATION, ser_pdev_obj);
290 	wlan_serialization_destroy_list(ser_pdev_obj,
291 					&ser_pdev_obj->active_list);
292 	wlan_serialization_destroy_list(ser_pdev_obj,
293 					&ser_pdev_obj->pending_list);
294 	wlan_serialization_destroy_list(ser_pdev_obj,
295 					&ser_pdev_obj->active_scan_list);
296 	wlan_serialization_destroy_list(ser_pdev_obj,
297 					&ser_pdev_obj->pending_scan_list);
298 	wlan_serialization_destroy_cmd_pool(ser_pdev_obj);
299 	serialization_debug("ser pdev obj detached with status %d", status);
300 	status = wlan_serialization_destroy_lock(ser_pdev_obj);
301 	if (status != QDF_STATUS_SUCCESS)
302 		serialization_err("Failed to destroy serialization lock");
303 	qdf_mem_free(ser_pdev_obj);
304 
305 	return status;
306 }
307 
308 /**
309  * wlan_serialization_vdev_obj_create_notification() - VDEV obj create callback
310  * @vdev: VDEV object
311  * @arg_list: Variable argument list
312  *
313  * This callback is registered with object manager during initialization and
314  * when obj manager gets its turn to create the object, it would notify each
315  * component with the corresponding callback registered to inform the
316  * completion of the creation of the respective object.
317  *
318  * Return: QDF Status
319  */
320 static QDF_STATUS wlan_serialization_vdev_obj_create_notification(
321 		struct wlan_objmgr_vdev *vdev, void *arg_list)
322 {
323 	return QDF_STATUS_SUCCESS;
324 }
325 
326 /**
327  * wlan_serialization_vdev_obj_destroy_notification() - vdev obj delete callback
328  * @vdev: VDEV object
329  * @arg_list: Variable argument list
330  *
331  * This callback is registered with object manager during initialization and
332  * when obj manager gets its turn to delete the object, it would notify each
333  * component with the corresponding callback registered to inform the
334  * completion of the deletion of the respective object.
335  *
336  * Return: QDF Status
337  */
338 static QDF_STATUS wlan_serialization_vdev_obj_destroy_notification(
339 		struct wlan_objmgr_vdev *vdev, void *arg_list)
340 {
341 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
342 
343 	if (!ser_legacy_cb.serialization_purge_cmd_list)
344 		return QDF_STATUS_SUCCESS;
345 
346 	serialization_debug("for vdev_id[%d] vdev[%pK] flush all cmds",
347 			  vdev_id, vdev);
348 	ser_legacy_cb.serialization_purge_cmd_list(wlan_vdev_get_psoc(vdev),
349 			vdev, false, false, false, false, true);
350 
351 	return QDF_STATUS_SUCCESS;
352 }
353 
354 QDF_STATUS wlan_serialization_init(void)
355 {
356 	QDF_STATUS status = QDF_STATUS_SUCCESS;
357 
358 	status = wlan_objmgr_register_psoc_create_handler(
359 			WLAN_UMAC_COMP_SERIALIZATION,
360 			wlan_serialization_psoc_obj_create_notification, NULL);
361 	if (status != QDF_STATUS_SUCCESS) {
362 		serialization_err("Failed to reg soc ser obj create handler");
363 		goto err_psoc_create;
364 	}
365 
366 	status = wlan_objmgr_register_psoc_destroy_handler(
367 			WLAN_UMAC_COMP_SERIALIZATION,
368 			wlan_serialization_psoc_obj_destroy_notification, NULL);
369 	if (status != QDF_STATUS_SUCCESS) {
370 		serialization_err("Failed to reg soc ser obj delete handler");
371 		goto err_psoc_delete;
372 	}
373 
374 	status = wlan_objmgr_register_pdev_create_handler(
375 			WLAN_UMAC_COMP_SERIALIZATION,
376 			wlan_serialization_pdev_obj_create_notification, NULL);
377 	if (status != QDF_STATUS_SUCCESS) {
378 		serialization_err("Failed to reg pdev ser obj create handler");
379 		goto err_pdev_create;
380 	}
381 
382 	status = wlan_objmgr_register_pdev_destroy_handler(
383 			WLAN_UMAC_COMP_SERIALIZATION,
384 			wlan_serialization_pdev_obj_destroy_notification, NULL);
385 	if (status != QDF_STATUS_SUCCESS) {
386 		serialization_err("Failed to reg pdev ser obj delete handler");
387 		goto err_pdev_delete;
388 	}
389 
390 	status = wlan_objmgr_register_vdev_create_handler(
391 			WLAN_UMAC_COMP_SERIALIZATION,
392 			wlan_serialization_vdev_obj_create_notification, NULL);
393 	if (status != QDF_STATUS_SUCCESS) {
394 		serialization_err("Failed to reg vdev ser obj create handler");
395 		goto err_vdev_create;
396 	}
397 
398 	status = wlan_objmgr_register_vdev_destroy_handler(
399 			WLAN_UMAC_COMP_SERIALIZATION,
400 			wlan_serialization_vdev_obj_destroy_notification, NULL);
401 	if (status != QDF_STATUS_SUCCESS) {
402 		serialization_err("Failed to reg vdev ser obj delete handler");
403 		goto err_vdev_delete;
404 	}
405 	serialization_debug("serialization handlers registered with obj mgr");
406 	/*
407 	 * Initialize the structure so all callbacks are registered
408 	 * initially as NULL.
409 	 */
410 	qdf_mem_zero(&ser_legacy_cb, sizeof(ser_legacy_cb));
411 
412 	return QDF_STATUS_SUCCESS;
413 
414 err_vdev_delete:
415 	wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_SERIALIZATION,
416 			wlan_serialization_vdev_obj_create_notification, NULL);
417 err_vdev_create:
418 	wlan_objmgr_unregister_pdev_destroy_handler(
419 			WLAN_UMAC_COMP_SERIALIZATION,
420 			wlan_serialization_pdev_obj_destroy_notification, NULL);
421 err_pdev_delete:
422 	wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_SERIALIZATION,
423 			wlan_serialization_pdev_obj_create_notification, NULL);
424 err_pdev_create:
425 	wlan_objmgr_unregister_psoc_destroy_handler(
426 			WLAN_UMAC_COMP_SERIALIZATION,
427 			wlan_serialization_psoc_obj_destroy_notification, NULL);
428 err_psoc_delete:
429 	wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_SERIALIZATION,
430 			 wlan_serialization_psoc_obj_create_notification, NULL);
431 err_psoc_create:
432 	return status;
433 
434 }
435 
436 QDF_STATUS wlan_serialization_deinit(void)
437 {
438 	QDF_STATUS status;
439 	QDF_STATUS ret_status = QDF_STATUS_SUCCESS;
440 
441 	status = wlan_objmgr_unregister_psoc_create_handler(
442 			WLAN_UMAC_COMP_SERIALIZATION,
443 			wlan_serialization_psoc_obj_create_notification,
444 			NULL);
445 	if (status != QDF_STATUS_SUCCESS) {
446 		serialization_err("unreg fail for psoc ser obj create notf:%d",
447 				status);
448 		ret_status = QDF_STATUS_E_FAILURE;
449 	}
450 	status = wlan_objmgr_unregister_psoc_destroy_handler(
451 			WLAN_UMAC_COMP_SERIALIZATION,
452 			wlan_serialization_psoc_obj_destroy_notification,
453 			NULL);
454 	if (status != QDF_STATUS_SUCCESS) {
455 		serialization_err("unreg fail for psoc ser obj destroy notf:%d",
456 				status);
457 		ret_status = QDF_STATUS_E_FAILURE;
458 	}
459 
460 	status = wlan_objmgr_unregister_pdev_create_handler(
461 			WLAN_UMAC_COMP_SERIALIZATION,
462 			wlan_serialization_pdev_obj_create_notification,
463 			NULL);
464 	if (status != QDF_STATUS_SUCCESS) {
465 		serialization_err("unreg fail for pdev ser obj create notf:%d",
466 				status);
467 		ret_status = QDF_STATUS_E_FAILURE;
468 	}
469 
470 	status = wlan_objmgr_unregister_pdev_destroy_handler(
471 			WLAN_UMAC_COMP_SERIALIZATION,
472 			wlan_serialization_pdev_obj_destroy_notification,
473 			NULL);
474 	if (status != QDF_STATUS_SUCCESS) {
475 		serialization_err("unreg fail for pdev ser destroy notf:%d",
476 				status);
477 		ret_status = QDF_STATUS_E_FAILURE;
478 	}
479 
480 	serialization_alert("deregistered callbacks with obj mgr successfully");
481 	/*
482 	 * Initialize the structure so all callbacks are registered
483 	 * initially as NULL.
484 	 */
485 	qdf_mem_zero(&ser_legacy_cb, sizeof(ser_legacy_cb));
486 
487 	return ret_status;
488 }
489