xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_main.c (revision d78dedc9dd8c4ee677ac1649d1d42f2a7c3cc1b7)
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 		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 	qdf_list_create(&ser_pdev_obj->active_list,
204 			WLAN_SERIALIZATION_MAX_ACTIVE_CMDS);
205 	qdf_list_create(&ser_pdev_obj->pending_list,
206 			WLAN_SERIALIZATION_MAX_GLOBAL_POOL_CMDS);
207 	qdf_list_create(&ser_pdev_obj->active_scan_list,
208 			WLAN_SERIALIZATION_MAX_ACTIVE_SCAN_CMDS);
209 	qdf_list_create(&ser_pdev_obj->pending_scan_list,
210 			WLAN_SERIALIZATION_MAX_GLOBAL_POOL_CMDS);
211 	qdf_list_create(&ser_pdev_obj->global_cmd_pool_list,
212 			WLAN_SERIALIZATION_MAX_GLOBAL_POOL_CMDS);
213 	status = wlan_serialization_create_cmd_pool(pdev, ser_pdev_obj);
214 	if (status != QDF_STATUS_SUCCESS) {
215 		serialization_err("ser_pdev_obj failed status %d", status);
216 		return status;
217 	}
218 	status = wlan_objmgr_pdev_component_obj_attach(pdev,
219 		WLAN_UMAC_COMP_SERIALIZATION, ser_pdev_obj,
220 		QDF_STATUS_SUCCESS);
221 	if (status != QDF_STATUS_SUCCESS) {
222 		serialization_err("serialization pdev obj attach failed");
223 		return status;
224 	}
225 
226 	return status;
227 }
228 
229 /**
230  * wlan_serialization_psoc_obj_destroy_notification() - PSOC obj delete callback
231  * @psoc: PSOC object
232  * @arg_list: Variable argument list
233  *
234  * This callback is registered with object manager during initialization and
235  * when obj manager gets its turn to delete the object, it would notify each
236  * component with the corresponding callback registered to inform the
237  * completion of the deletion of the respective object.
238  *
239  * Return: QDF Status
240  */
241 static QDF_STATUS wlan_serialization_psoc_obj_destroy_notification(
242 		struct wlan_objmgr_psoc *psoc, void *arg_list)
243 {
244 	QDF_STATUS status;
245 	struct wlan_serialization_psoc_priv_obj *ser_soc_obj =
246 		wlan_serialization_get_psoc_priv_obj(psoc);
247 
248 	if (NULL == ser_soc_obj) {
249 		serialization_err("invalid ser_soc_obj");
250 		return QDF_STATUS_E_FAULT;
251 	}
252 	status = wlan_objmgr_psoc_component_obj_detach(psoc,
253 			WLAN_UMAC_COMP_SERIALIZATION,
254 			ser_soc_obj);
255 	if (status != QDF_STATUS_SUCCESS)
256 		serialization_err("ser psoc private obj detach failed");
257 	serialization_debug("ser psoc obj deleted with status %d", status);
258 	qdf_mem_free(ser_soc_obj);
259 
260 	return status;
261 }
262 
263 /**
264  * wlan_serialization_pdev_obj_destroy_notification() - PDEV obj delete callback
265  * @pdev: PDEV object
266  * @arg_list: Variable argument list
267  *
268  * This callback is registered with object manager during initialization and
269  * when obj manager gets its turn to delete the object, it would notify each
270  * component with the corresponding callback registered to inform the
271  * completion of the deletion of the respective object.
272  *
273  * Return: QDF Status
274  */
275 static QDF_STATUS wlan_serialization_pdev_obj_destroy_notification(
276 		struct wlan_objmgr_pdev *pdev, void *arg_list)
277 {
278 	QDF_STATUS status;
279 	struct wlan_serialization_pdev_priv_obj *ser_pdev_obj =
280 		wlan_serialization_get_pdev_priv_obj(pdev);
281 
282 	status = wlan_objmgr_pdev_component_obj_detach(pdev,
283 			WLAN_UMAC_COMP_SERIALIZATION, ser_pdev_obj);
284 	wlan_serialization_destroy_list(ser_pdev_obj,
285 					&ser_pdev_obj->active_list);
286 	wlan_serialization_destroy_list(ser_pdev_obj,
287 					&ser_pdev_obj->pending_list);
288 	wlan_serialization_destroy_list(ser_pdev_obj,
289 					&ser_pdev_obj->active_scan_list);
290 	wlan_serialization_destroy_list(ser_pdev_obj,
291 					&ser_pdev_obj->pending_scan_list);
292 	wlan_serialization_destroy_cmd_pool(ser_pdev_obj);
293 	serialization_debug("ser pdev obj deleted with status %d", status);
294 	qdf_mem_free(ser_pdev_obj);
295 
296 	return status;
297 }
298 
299 /**
300  * wlan_serialization_vdev_obj_create_notification() - VDEV obj create callback
301  * @vdev: VDEV object
302  * @arg_list: Variable argument list
303  *
304  * This callback is registered with object manager during initialization and
305  * when obj manager gets its turn to create the object, it would notify each
306  * component with the corresponding callback registered to inform the
307  * completion of the creation of the respective object.
308  *
309  * Return: QDF Status
310  */
311 static QDF_STATUS wlan_serialization_vdev_obj_create_notification(
312 		struct wlan_objmgr_vdev *vdev, void *arg_list)
313 {
314 	return QDF_STATUS_SUCCESS;
315 }
316 
317 /**
318  * wlan_serialization_vdev_obj_destroy_notification() - vdev obj delete callback
319  * @vdev: VDEV object
320  * @arg_list: Variable argument list
321  *
322  * This callback is registered with object manager during initialization and
323  * when obj manager gets its turn to delete the object, it would notify each
324  * component with the corresponding callback registered to inform the
325  * completion of the deletion of the respective object.
326  *
327  * Return: QDF Status
328  */
329 static QDF_STATUS wlan_serialization_vdev_obj_destroy_notification(
330 		struct wlan_objmgr_vdev *vdev, void *arg_list)
331 {
332 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
333 
334 	if (!ser_legacy_cb.serialization_purge_cmd_list)
335 		return QDF_STATUS_SUCCESS;
336 
337 	serialization_debug("for vdev_id[%d] vdev[%pK] flush all cmds",
338 			  vdev_id, vdev);
339 	ser_legacy_cb.serialization_purge_cmd_list(wlan_vdev_get_psoc(vdev),
340 			vdev, false, false, false, false, true);
341 
342 	return QDF_STATUS_SUCCESS;
343 }
344 
345 QDF_STATUS wlan_serialization_init(void)
346 {
347 	QDF_STATUS status = QDF_STATUS_SUCCESS;
348 
349 	status = wlan_objmgr_register_psoc_create_handler(
350 			WLAN_UMAC_COMP_SERIALIZATION,
351 			wlan_serialization_psoc_obj_create_notification, NULL);
352 	if (status != QDF_STATUS_SUCCESS) {
353 		serialization_err("Failed to reg soc ser obj create handler");
354 		goto err_psoc_create;
355 	}
356 
357 	status = wlan_objmgr_register_psoc_destroy_handler(
358 			WLAN_UMAC_COMP_SERIALIZATION,
359 			wlan_serialization_psoc_obj_destroy_notification, NULL);
360 	if (status != QDF_STATUS_SUCCESS) {
361 		serialization_err("Failed to reg soc ser obj delete handler");
362 		goto err_psoc_delete;
363 	}
364 
365 	status = wlan_objmgr_register_pdev_create_handler(
366 			WLAN_UMAC_COMP_SERIALIZATION,
367 			wlan_serialization_pdev_obj_create_notification, NULL);
368 	if (status != QDF_STATUS_SUCCESS) {
369 		serialization_err("Failed to reg pdev ser obj create handler");
370 		goto err_pdev_create;
371 	}
372 
373 	status = wlan_objmgr_register_pdev_destroy_handler(
374 			WLAN_UMAC_COMP_SERIALIZATION,
375 			wlan_serialization_pdev_obj_destroy_notification, NULL);
376 	if (status != QDF_STATUS_SUCCESS) {
377 		serialization_err("Failed to reg pdev ser obj delete handler");
378 		goto err_pdev_delete;
379 	}
380 
381 	status = wlan_objmgr_register_vdev_create_handler(
382 			WLAN_UMAC_COMP_SERIALIZATION,
383 			wlan_serialization_vdev_obj_create_notification, NULL);
384 	if (status != QDF_STATUS_SUCCESS) {
385 		serialization_err("Failed to reg vdev ser obj create handler");
386 		goto err_vdev_create;
387 	}
388 
389 	status = wlan_objmgr_register_vdev_destroy_handler(
390 			WLAN_UMAC_COMP_SERIALIZATION,
391 			wlan_serialization_vdev_obj_destroy_notification, NULL);
392 	if (status != QDF_STATUS_SUCCESS) {
393 		serialization_err("Failed to reg vdev ser obj delete handler");
394 		goto err_vdev_delete;
395 	}
396 	serialization_debug("serialization handlers registered with obj mgr");
397 	/*
398 	 * Initialize the structure so all callbacks are registered
399 	 * initially as NULL.
400 	 */
401 	qdf_mem_zero(&ser_legacy_cb, sizeof(ser_legacy_cb));
402 
403 	return QDF_STATUS_SUCCESS;
404 
405 err_vdev_delete:
406 	wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_SERIALIZATION,
407 			wlan_serialization_vdev_obj_create_notification, NULL);
408 err_vdev_create:
409 	wlan_objmgr_unregister_pdev_destroy_handler(
410 			WLAN_UMAC_COMP_SERIALIZATION,
411 			wlan_serialization_pdev_obj_destroy_notification, NULL);
412 err_pdev_delete:
413 	wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_SERIALIZATION,
414 			wlan_serialization_pdev_obj_create_notification, NULL);
415 err_pdev_create:
416 	wlan_objmgr_unregister_psoc_destroy_handler(
417 			WLAN_UMAC_COMP_SERIALIZATION,
418 			wlan_serialization_psoc_obj_destroy_notification, NULL);
419 err_psoc_delete:
420 	wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_SERIALIZATION,
421 			 wlan_serialization_psoc_obj_create_notification, NULL);
422 err_psoc_create:
423 	return status;
424 
425 }
426 
427 QDF_STATUS wlan_serialization_deinit(void)
428 {
429 	QDF_STATUS status;
430 	QDF_STATUS ret_status = QDF_STATUS_SUCCESS;
431 
432 	status = wlan_objmgr_unregister_psoc_create_handler(
433 			WLAN_UMAC_COMP_SERIALIZATION,
434 			wlan_serialization_psoc_obj_create_notification,
435 			NULL);
436 	if (status != QDF_STATUS_SUCCESS) {
437 		serialization_err("unreg fail for psoc ser obj create notf:%d",
438 				status);
439 		ret_status = QDF_STATUS_E_FAILURE;
440 	}
441 	status = wlan_objmgr_unregister_psoc_destroy_handler(
442 			WLAN_UMAC_COMP_SERIALIZATION,
443 			wlan_serialization_psoc_obj_destroy_notification,
444 			NULL);
445 	if (status != QDF_STATUS_SUCCESS) {
446 		serialization_err("unreg fail for psoc ser obj destroy notf:%d",
447 				status);
448 		ret_status = QDF_STATUS_E_FAILURE;
449 	}
450 
451 	status = wlan_objmgr_unregister_pdev_create_handler(
452 			WLAN_UMAC_COMP_SERIALIZATION,
453 			wlan_serialization_pdev_obj_create_notification,
454 			NULL);
455 	if (status != QDF_STATUS_SUCCESS) {
456 		serialization_err("unreg fail for pdev ser obj create notf:%d",
457 				status);
458 		ret_status = QDF_STATUS_E_FAILURE;
459 	}
460 
461 	status = wlan_objmgr_unregister_pdev_destroy_handler(
462 			WLAN_UMAC_COMP_SERIALIZATION,
463 			wlan_serialization_pdev_obj_destroy_notification,
464 			NULL);
465 	if (status != QDF_STATUS_SUCCESS) {
466 		serialization_err("unreg fail for pdev ser destroy notf:%d",
467 				status);
468 		ret_status = QDF_STATUS_E_FAILURE;
469 	}
470 
471 	serialization_alert("deregistered callbacks with obj mgr successfully");
472 	/*
473 	 * Initialize the structure so all callbacks are registered
474 	 * initially as NULL.
475 	 */
476 	qdf_mem_zero(&ser_legacy_cb, sizeof(ser_legacy_cb));
477 
478 	return ret_status;
479 }
480