1 /*
2  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /**
21  * DOC: wlan_serialization_utils.c
22  * This file defines the utility helper functions for serialization component.
23  */
24 
25 #include <wlan_objmgr_vdev_obj.h>
26 #include <wlan_objmgr_pdev_obj.h>
27 #include <qdf_mc_timer.h>
28 #include <wlan_utility.h>
29 #include "wlan_serialization_utils_i.h"
30 #include "wlan_serialization_main_i.h"
31 #include "wlan_serialization_queue_i.h"
32 #include "wlan_serialization_api.h"
33 
34 #ifndef WLAN_SER_DEBUG
wlan_ser_update_cmd_history(struct wlan_serialization_pdev_queue * pdev_queue,struct wlan_serialization_command * cmd,enum ser_queue_reason ser_reason,bool add_remove,bool active_queue)35 void wlan_ser_update_cmd_history(
36 		struct wlan_serialization_pdev_queue *pdev_queue,
37 		struct wlan_serialization_command *cmd,
38 		enum ser_queue_reason ser_reason,
39 		bool add_remove,
40 		bool active_queue){ }
41 #endif
42 
43 struct wlan_objmgr_pdev*
wlan_serialization_get_pdev_from_cmd(struct wlan_serialization_command * cmd)44 wlan_serialization_get_pdev_from_cmd(struct wlan_serialization_command *cmd)
45 {
46 	struct wlan_objmgr_pdev *pdev = NULL;
47 
48 	if (!cmd) {
49 		ser_err("invalid cmd");
50 		return pdev;
51 	}
52 	if (!cmd->vdev) {
53 		ser_err("invalid cmd->vdev");
54 		return pdev;
55 	}
56 	pdev = wlan_vdev_get_pdev(cmd->vdev);
57 
58 	return pdev;
59 }
60 
61 struct wlan_objmgr_psoc*
wlan_serialization_get_psoc_from_cmd(struct wlan_serialization_command * cmd)62 wlan_serialization_get_psoc_from_cmd(struct wlan_serialization_command *cmd)
63 {
64 	struct wlan_objmgr_psoc *psoc = NULL;
65 
66 	if (!cmd) {
67 		ser_err("invalid cmd");
68 		return psoc;
69 	}
70 	if (!cmd->vdev) {
71 		ser_err("invalid cmd->vdev");
72 		return psoc;
73 	}
74 	psoc = wlan_vdev_get_psoc(cmd->vdev);
75 
76 	return psoc;
77 }
78 
79 struct wlan_objmgr_vdev*
wlan_serialization_get_vdev_from_cmd(struct wlan_serialization_command * cmd)80 wlan_serialization_get_vdev_from_cmd(struct wlan_serialization_command *cmd)
81 {
82 	struct wlan_objmgr_vdev *vdev = NULL;
83 
84 	if (!cmd) {
85 		ser_err("invalid cmd");
86 		goto error;
87 	}
88 
89 	vdev = cmd->vdev;
90 
91 error:
92 	return vdev;
93 }
94 
95 QDF_STATUS
wlan_serialization_get_cmd_from_queue(qdf_list_t * queue,qdf_list_node_t ** nnode)96 wlan_serialization_get_cmd_from_queue(qdf_list_t *queue,
97 				      qdf_list_node_t **nnode)
98 {
99 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
100 	qdf_list_node_t *pnode;
101 
102 	if (!queue) {
103 		ser_err("input parameters are invalid");
104 		goto error;
105 	}
106 
107 	pnode = *nnode;
108 	if (!pnode)
109 		status = wlan_serialization_peek_front(queue, nnode);
110 	else
111 		status = wlan_serialization_peek_next(queue, pnode, nnode);
112 
113 	if (status != QDF_STATUS_SUCCESS)
114 		ser_err("can't get next node from queue");
115 
116 error:
117 	return status;
118 }
119 
wlan_serialization_timer_destroy(struct wlan_serialization_timer * ser_timer)120 QDF_STATUS wlan_serialization_timer_destroy(
121 		struct wlan_serialization_timer *ser_timer)
122 {
123 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
124 
125 	if (!ser_timer || !ser_timer->cmd) {
126 		ser_debug("Invalid ser_timer");
127 		qdf_status =  QDF_STATUS_E_FAILURE;
128 		goto error;
129 	}
130 	/* Wait till timeout CB is completed */
131 	qdf_timer_sync_cancel(&ser_timer->timer);
132 	ser_timer->cmd = NULL;
133 
134 error:
135 	return qdf_status;
136 }
137 
138 QDF_STATUS
wlan_serialization_stop_timer(struct wlan_serialization_timer * ser_timer)139 wlan_serialization_stop_timer(struct wlan_serialization_timer *ser_timer)
140 {
141 	wlan_serialization_timer_destroy(ser_timer);
142 
143 	return QDF_STATUS_SUCCESS;
144 }
145 
wlan_serialization_cleanup_vdev_timers(struct wlan_objmgr_vdev * vdev)146 QDF_STATUS wlan_serialization_cleanup_vdev_timers(
147 			struct wlan_objmgr_vdev *vdev)
148 {
149 	struct wlan_ser_psoc_obj *psoc_ser_obj;
150 	struct wlan_serialization_timer *ser_timer;
151 	QDF_STATUS status = QDF_STATUS_SUCCESS;
152 	uint32_t i = 0;
153 	struct wlan_objmgr_pdev *pdev = NULL;
154 	struct wlan_objmgr_psoc *psoc = NULL;
155 
156 	pdev = wlan_vdev_get_pdev(vdev);
157 	if (!pdev) {
158 		QDF_BUG(0);
159 		ser_err("pdev is null");
160 		status = QDF_STATUS_E_FAILURE;
161 		goto error;
162 	}
163 
164 	psoc = wlan_pdev_get_psoc(pdev);
165 	if (!psoc) {
166 		QDF_BUG(0);
167 		ser_err("psoc is null");
168 		status = QDF_STATUS_E_FAILURE;
169 		goto error;
170 	}
171 
172 	psoc_ser_obj = wlan_serialization_get_psoc_obj(psoc);
173 
174 	if (!psoc_ser_obj) {
175 		ser_err("Invalid psoc_ser_obj");
176 		status = QDF_STATUS_E_FAILURE;
177 		goto error;
178 	}
179 
180 	wlan_serialization_acquire_lock(&psoc_ser_obj->timer_lock);
181 
182 	for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) {
183 		ser_timer = &psoc_ser_obj->timers[i];
184 		if (!ser_timer->cmd)
185 			continue;
186 		/*
187 		 * Check if the timer is for the given vdev
188 		 */
189 		if (ser_timer->cmd->vdev != vdev)
190 			continue;
191 
192 		ser_debug("Stopping the timer for vdev id[%d]",
193 			  wlan_vdev_get_id(vdev));
194 
195 		status = wlan_serialization_stop_timer(ser_timer);
196 		if (QDF_STATUS_SUCCESS != status) {
197 			/* lets not break the loop but report error */
198 			ser_err("some error in stopping timer");
199 		}
200 	}
201 
202 	wlan_serialization_release_lock(&psoc_ser_obj->timer_lock);
203 error:
204 	return status;
205 }
206 
wlan_serialization_cleanup_all_timers(struct wlan_ser_psoc_obj * psoc_ser_obj)207 QDF_STATUS wlan_serialization_cleanup_all_timers(
208 			struct wlan_ser_psoc_obj *psoc_ser_obj)
209 {
210 	struct wlan_serialization_timer *ser_timer;
211 	QDF_STATUS status = QDF_STATUS_SUCCESS;
212 	uint32_t i = 0;
213 
214 	if (!psoc_ser_obj) {
215 		ser_err("Invalid psoc_ser_obj");
216 		status = QDF_STATUS_E_FAILURE;
217 		goto error;
218 	}
219 
220 	wlan_serialization_acquire_lock(&psoc_ser_obj->timer_lock);
221 
222 	for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) {
223 		ser_timer = &psoc_ser_obj->timers[i];
224 		if (!ser_timer->cmd)
225 			continue;
226 		status = wlan_serialization_stop_timer(ser_timer);
227 		if (QDF_STATUS_SUCCESS != status) {
228 			/* lets not break the loop but report error */
229 			ser_err("some error in stopping timer");
230 		}
231 	}
232 
233 	wlan_serialization_release_lock(&psoc_ser_obj->timer_lock);
234 error:
235 
236 	return status;
237 }
238 
wlan_serialization_validate_cmdtype(enum wlan_serialization_cmd_type cmd_type)239 QDF_STATUS wlan_serialization_validate_cmdtype(
240 		 enum wlan_serialization_cmd_type cmd_type)
241 {
242 	if (cmd_type < 0 || cmd_type >= WLAN_SER_CMD_MAX) {
243 		ser_err("Invalid cmd %d passed", cmd_type);
244 		return QDF_STATUS_E_INVAL;
245 	}
246 
247 	return QDF_STATUS_SUCCESS;
248 }
249 
wlan_serialization_validate_cmd(enum wlan_umac_comp_id comp_id,enum wlan_serialization_cmd_type cmd_type)250 QDF_STATUS wlan_serialization_validate_cmd(
251 		 enum wlan_umac_comp_id comp_id,
252 		 enum wlan_serialization_cmd_type cmd_type)
253 {
254 	QDF_STATUS status = QDF_STATUS_E_INVAL;
255 
256 	if (cmd_type < 0 || comp_id < 0 || cmd_type >= WLAN_SER_CMD_MAX ||
257 	    comp_id >= WLAN_UMAC_COMP_ID_MAX) {
258 		ser_err("Invalid cmd or comp passed comp %d type %d",
259 			comp_id, cmd_type);
260 		goto error;
261 	}
262 
263 	status = QDF_STATUS_SUCCESS;
264 error:
265 	return status;
266 }
267 
wlan_serialization_validate_cmd_list(struct wlan_serialization_command_list * cmd_list)268 QDF_STATUS wlan_serialization_validate_cmd_list(
269 		struct wlan_serialization_command_list *cmd_list)
270 {
271 	QDF_STATUS status = QDF_STATUS_E_INVAL;
272 
273 	if (!cmd_list->cmd.cmd_cb) {
274 		ser_err("no cmd_cb for cmd type:%d, id: %d",
275 			cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id);
276 		QDF_ASSERT(0);
277 		goto error;
278 	}
279 
280 	if (!cmd_list->cmd.vdev) {
281 		ser_err("invalid cmd.vdev");
282 		goto error;
283 	}
284 
285 	status = QDF_STATUS_SUCCESS;
286 
287 error:
288 	return status;
289 }
290 
wlan_serialization_release_pdev_list_cmds(struct wlan_serialization_pdev_queue * pdev_queue)291 static void wlan_serialization_release_pdev_list_cmds(
292 		struct wlan_serialization_pdev_queue *pdev_queue)
293 {
294 	qdf_list_node_t *node = NULL;
295 
296 	while (!wlan_serialization_list_empty(&pdev_queue->active_list)) {
297 		wlan_serialization_remove_front(
298 				&pdev_queue->active_list, &node);
299 		wlan_serialization_insert_back(
300 				&pdev_queue->cmd_pool_list, node);
301 	}
302 
303 	while (!wlan_serialization_list_empty(&pdev_queue->pending_list)) {
304 		wlan_serialization_remove_front(
305 				&pdev_queue->pending_list, &node);
306 		wlan_serialization_insert_back(
307 				&pdev_queue->cmd_pool_list, node);
308 	}
309 
310 }
311 
wlan_serialization_release_vdev_list_cmds(qdf_list_t * list)312 static void wlan_serialization_release_vdev_list_cmds(qdf_list_t *list)
313 {
314 	qdf_list_node_t *node = NULL;
315 
316 
317 	while (!wlan_serialization_list_empty(list))
318 		wlan_serialization_remove_front(list, &node);
319 
320 }
321 
wlan_serialization_destroy_pdev_list(struct wlan_serialization_pdev_queue * pdev_queue)322 void wlan_serialization_destroy_pdev_list(
323 		struct wlan_serialization_pdev_queue *pdev_queue)
324 {
325 
326 	wlan_serialization_release_pdev_list_cmds(pdev_queue);
327 	qdf_list_destroy(&pdev_queue->pending_list);
328 	qdf_list_destroy(&pdev_queue->active_list);
329 
330 }
331 
wlan_serialization_destroy_vdev_list(qdf_list_t * list)332 void wlan_serialization_destroy_vdev_list(qdf_list_t *list)
333 {
334 
335 	wlan_serialization_release_vdev_list_cmds(list);
336 	qdf_list_destroy(list);
337 
338 }
339 
wlan_serialization_get_psoc_obj(struct wlan_objmgr_psoc * psoc)340 struct wlan_ser_psoc_obj *wlan_serialization_get_psoc_obj(
341 		struct wlan_objmgr_psoc *psoc)
342 {
343 	struct wlan_ser_psoc_obj *ser_soc_obj;
344 
345 	ser_soc_obj =
346 		wlan_objmgr_psoc_get_comp_private_obj(
347 				psoc, WLAN_UMAC_COMP_SERIALIZATION);
348 
349 	return ser_soc_obj;
350 }
351 
wlan_serialization_get_pdev_obj(struct wlan_objmgr_pdev * pdev)352 struct wlan_ser_pdev_obj *wlan_serialization_get_pdev_obj(
353 		struct wlan_objmgr_pdev *pdev)
354 {
355 	struct wlan_ser_pdev_obj *obj;
356 
357 	obj = wlan_objmgr_pdev_get_comp_private_obj(
358 			pdev, WLAN_UMAC_COMP_SERIALIZATION);
359 
360 	return obj;
361 }
362 
wlan_serialization_get_vdev_obj(struct wlan_objmgr_vdev * vdev)363 struct wlan_ser_vdev_obj *wlan_serialization_get_vdev_obj(
364 		struct wlan_objmgr_vdev *vdev)
365 {
366 	struct wlan_ser_vdev_obj *obj;
367 
368 	obj = wlan_objmgr_vdev_get_comp_private_obj(
369 			vdev, WLAN_UMAC_COMP_SERIALIZATION);
370 
371 	return obj;
372 }
373 
wlan_serialization_is_cmd_in_vdev_list(struct wlan_objmgr_vdev * vdev,qdf_list_t * queue,enum wlan_serialization_node node_type)374 bool wlan_serialization_is_cmd_in_vdev_list(
375 		struct wlan_objmgr_vdev *vdev,
376 		qdf_list_t *queue,
377 		enum wlan_serialization_node node_type)
378 {
379 	qdf_list_node_t *node = NULL;
380 	bool cmd_found = false;
381 
382 	node = wlan_serialization_find_cmd(
383 			queue, WLAN_SER_MATCH_VDEV,
384 			NULL, 0, NULL, vdev, node_type);
385 
386 	if (node)
387 		cmd_found = true;
388 
389 	return cmd_found;
390 }
391 
wlan_serialization_is_cmd_in_pdev_list(struct wlan_objmgr_pdev * pdev,qdf_list_t * queue)392 bool wlan_serialization_is_cmd_in_pdev_list(
393 			struct wlan_objmgr_pdev *pdev,
394 			qdf_list_t *queue)
395 {
396 	qdf_list_node_t *node = NULL;
397 	bool cmd_found = false;
398 
399 	node = wlan_serialization_find_cmd(
400 			queue, WLAN_SER_MATCH_PDEV,
401 			NULL, 0, pdev, NULL,  WLAN_SER_PDEV_NODE);
402 
403 	if (node)
404 		cmd_found = true;
405 
406 	return cmd_found;
407 }
408 
409 enum wlan_serialization_cmd_status
wlan_serialization_is_cmd_in_active_pending(bool cmd_in_active,bool cmd_in_pending)410 wlan_serialization_is_cmd_in_active_pending(bool cmd_in_active,
411 					    bool cmd_in_pending)
412 {
413 	enum wlan_serialization_cmd_status status;
414 
415 	if (cmd_in_active && cmd_in_pending)
416 		status = WLAN_SER_CMDS_IN_ALL_LISTS;
417 	else if (cmd_in_active)
418 		status = WLAN_SER_CMD_IN_ACTIVE_LIST;
419 	else if (cmd_in_pending)
420 		status = WLAN_SER_CMD_IN_PENDING_LIST;
421 	else
422 		status = WLAN_SER_CMD_NOT_FOUND;
423 
424 	return status;
425 }
426 
427 bool
wlan_serialization_is_cmd_present_in_given_queue(qdf_list_t * queue,struct wlan_serialization_command * cmd,enum wlan_serialization_node node_type)428 wlan_serialization_is_cmd_present_in_given_queue(
429 		qdf_list_t *queue,
430 		struct wlan_serialization_command *cmd,
431 		enum wlan_serialization_node node_type)
432 {
433 	qdf_list_node_t *node = NULL;
434 	bool found = false;
435 
436 	node = wlan_serialization_find_cmd(
437 			queue, WLAN_SER_MATCH_CMD_ID_VDEV,
438 			cmd, 0, NULL, cmd->vdev, node_type);
439 
440 	if (node)
441 		found = true;
442 
443 	return found;
444 }
445 
446 QDF_STATUS
wlan_serialization_remove_cmd_from_queue(qdf_list_t * queue,struct wlan_serialization_command * cmd,struct wlan_serialization_command_list ** pcmd_list,struct wlan_ser_pdev_obj * ser_pdev_obj,enum wlan_serialization_node node_type)447 wlan_serialization_remove_cmd_from_queue(
448 		qdf_list_t *queue,
449 		struct wlan_serialization_command *cmd,
450 		struct wlan_serialization_command_list **pcmd_list,
451 		struct wlan_ser_pdev_obj *ser_pdev_obj,
452 		enum wlan_serialization_node node_type)
453 {
454 	struct wlan_serialization_command_list *cmd_list;
455 	qdf_list_node_t *node = NULL;
456 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
457 
458 	if (!cmd)
459 		goto error;
460 
461 	if (!queue || wlan_serialization_list_empty(queue)) {
462 		ser_debug("Empty queue");
463 		goto error;
464 	}
465 
466 	node = wlan_serialization_find_cmd(queue, WLAN_SER_MATCH_CMD_ID_VDEV,
467 					   cmd, 0, NULL, cmd->vdev, node_type);
468 
469 	if (!node) {
470 		ser_info("fail to find node %d for removal", node_type);
471 		goto error;
472 	}
473 
474 	if (node_type == WLAN_SER_PDEV_NODE)
475 		cmd_list =
476 			qdf_container_of(node,
477 					 struct wlan_serialization_command_list,
478 					 pdev_node);
479 	else
480 		cmd_list =
481 			qdf_container_of(node,
482 					 struct wlan_serialization_command_list,
483 					 vdev_node);
484 
485 	if (qdf_atomic_test_bit(CMD_MARKED_FOR_ACTIVATION,
486 				&cmd_list->cmd_in_use)) {
487 		qdf_atomic_set_bit(CMD_ACTIVE_MARKED_FOR_REMOVAL,
488 				   &cmd_list->cmd_in_use);
489 		status = QDF_STATUS_E_PENDING;
490 		goto error;
491 	}
492 
493 	status = wlan_serialization_remove_node(queue, node);
494 
495 	if (QDF_STATUS_SUCCESS != status)
496 		ser_err("Fail to add to free pool type %d",
497 			cmd->cmd_type);
498 
499 	*pcmd_list = cmd_list;
500 
501 error:
502 	return status;
503 }
504 
505 enum wlan_serialization_status
wlan_serialization_add_cmd_to_queue(qdf_list_t * queue,struct wlan_serialization_command_list * cmd_list,struct wlan_ser_pdev_obj * ser_pdev_obj,uint8_t is_cmd_for_active_queue,enum wlan_serialization_node node_type)506 wlan_serialization_add_cmd_to_queue(
507 		qdf_list_t *queue,
508 		struct wlan_serialization_command_list *cmd_list,
509 		struct wlan_ser_pdev_obj *ser_pdev_obj,
510 		uint8_t is_cmd_for_active_queue,
511 		enum wlan_serialization_node node_type)
512 {
513 	enum wlan_serialization_status status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
514 	QDF_STATUS qdf_status;
515 	qdf_list_node_t *node;
516 
517 	if (!cmd_list || !queue || !ser_pdev_obj) {
518 		ser_err("Input arguments are not valid");
519 		goto error;
520 	}
521 
522 	if (node_type == WLAN_SER_PDEV_NODE)
523 		node = &cmd_list->pdev_node;
524 	else
525 		node = &cmd_list->vdev_node;
526 
527 	if (qdf_list_size(queue) == qdf_list_max_size(queue)) {
528 		status = WLAN_SER_CMD_DENIED_LIST_FULL;
529 		ser_err("Queue size reached max %d, fail to add type %d id %d",
530 			qdf_list_max_size(queue), cmd_list->cmd.cmd_type,
531 			cmd_list->cmd.cmd_id);
532 		goto error;
533 	}
534 
535 	if (cmd_list->cmd.is_high_priority)
536 		qdf_status = wlan_serialization_insert_front(queue, node);
537 	else
538 		qdf_status = wlan_serialization_insert_back(queue, node);
539 
540 	if (QDF_IS_STATUS_ERROR(qdf_status))
541 		goto error;
542 
543 	if (is_cmd_for_active_queue)
544 		status = WLAN_SER_CMD_ACTIVE;
545 	else
546 		status = WLAN_SER_CMD_PENDING;
547 
548 error:
549 	return status;
550 }
551 
wlan_serialization_list_empty(qdf_list_t * queue)552 bool wlan_serialization_list_empty(qdf_list_t *queue)
553 {
554 	bool is_empty;
555 
556 	if (qdf_list_empty(queue))
557 		is_empty = true;
558 	else
559 		is_empty = false;
560 
561 	return is_empty;
562 }
563 
wlan_serialization_list_size(qdf_list_t * queue)564 uint32_t wlan_serialization_list_size(qdf_list_t *queue)
565 {
566 	uint32_t size;
567 
568 	size = qdf_list_size(queue);
569 
570 	return size;
571 }
572 
wlan_serialization_remove_front(qdf_list_t * list,qdf_list_node_t ** node)573 QDF_STATUS wlan_serialization_remove_front(qdf_list_t *list,
574 					   qdf_list_node_t **node)
575 {
576 	QDF_STATUS status;
577 
578 	if (wlan_serialization_list_empty(list)) {
579 		ser_err("The list is empty");
580 		status = QDF_STATUS_E_EMPTY;
581 		goto error;
582 	}
583 
584 	status = qdf_list_remove_front(list, node);
585 error:
586 	return status;
587 }
588 
wlan_serialization_remove_node(qdf_list_t * list,qdf_list_node_t * node)589 QDF_STATUS wlan_serialization_remove_node(qdf_list_t *list,
590 					  qdf_list_node_t *node)
591 {
592 	QDF_STATUS status;
593 
594 	if (wlan_serialization_list_empty(list)) {
595 		ser_err("The list is empty");
596 		status = QDF_STATUS_E_EMPTY;
597 		goto error;
598 	}
599 	status = qdf_list_remove_node(list, node);
600 
601 error:
602 	return status;
603 }
604 
wlan_serialization_insert_front(qdf_list_t * list,qdf_list_node_t * node)605 QDF_STATUS wlan_serialization_insert_front(qdf_list_t *list,
606 					   qdf_list_node_t *node)
607 {
608 	QDF_STATUS status;
609 
610 	status = qdf_list_insert_front(list, node);
611 
612 	return status;
613 }
614 
wlan_serialization_insert_back(qdf_list_t * list,qdf_list_node_t * node)615 QDF_STATUS wlan_serialization_insert_back(qdf_list_t *list,
616 					  qdf_list_node_t *node)
617 {
618 	QDF_STATUS status;
619 
620 	status = qdf_list_insert_back(list, node);
621 
622 	return status;
623 }
624 
wlan_serialization_peek_front(qdf_list_t * list,qdf_list_node_t ** node)625 QDF_STATUS wlan_serialization_peek_front(qdf_list_t *list,
626 					 qdf_list_node_t **node)
627 {
628 	QDF_STATUS status;
629 
630 	status = qdf_list_peek_front(list, node);
631 
632 	return status;
633 }
634 
wlan_serialization_peek_next(qdf_list_t * list,qdf_list_node_t * node1,qdf_list_node_t ** node2)635 QDF_STATUS wlan_serialization_peek_next(qdf_list_t *list,
636 					qdf_list_node_t *node1,
637 					qdf_list_node_t **node2)
638 {
639 	QDF_STATUS status;
640 
641 	status = qdf_list_peek_next(list, node1, node2);
642 
643 	return status;
644 }
645 
646 bool
wlan_serialization_match_cmd_type(qdf_list_node_t * nnode,enum wlan_serialization_cmd_type cmd_type,enum wlan_serialization_node node_type)647 wlan_serialization_match_cmd_type(qdf_list_node_t *nnode,
648 				  enum wlan_serialization_cmd_type cmd_type,
649 				  enum wlan_serialization_node node_type)
650 {
651 	struct wlan_serialization_command_list *cmd_list = NULL;
652 	bool match_found = true;
653 
654 	if (node_type == WLAN_SER_PDEV_NODE)
655 		cmd_list =
656 			qdf_container_of(nnode,
657 					 struct wlan_serialization_command_list,
658 					 pdev_node);
659 	else
660 		cmd_list =
661 			qdf_container_of(nnode,
662 					 struct wlan_serialization_command_list,
663 					 vdev_node);
664 
665 	if (cmd_list->cmd.cmd_type != cmd_type)
666 		match_found = false;
667 
668 	return match_found;
669 }
670 
671 bool
wlan_serialization_match_cmd_id_type(qdf_list_node_t * nnode,struct wlan_serialization_command * cmd,enum wlan_serialization_node node_type)672 wlan_serialization_match_cmd_id_type(qdf_list_node_t *nnode,
673 				     struct wlan_serialization_command *cmd,
674 				     enum wlan_serialization_node node_type)
675 {
676 	struct wlan_serialization_command_list *cmd_list = NULL;
677 	bool match_found = true;
678 
679 	if (!cmd) {
680 		match_found = false;
681 		goto error;
682 	}
683 
684 	if (node_type == WLAN_SER_PDEV_NODE)
685 		cmd_list =
686 			qdf_container_of(nnode,
687 					 struct wlan_serialization_command_list,
688 					 pdev_node);
689 	else
690 		cmd_list =
691 			qdf_container_of(nnode,
692 					 struct wlan_serialization_command_list,
693 					 vdev_node);
694 
695 	if ((cmd_list->cmd.cmd_id != cmd->cmd_id) ||
696 	    (cmd_list->cmd.cmd_type != cmd->cmd_type)) {
697 		match_found = false;
698 	};
699 
700 error:
701 	return match_found;
702 }
703 
wlan_serialization_match_cmd_vdev(qdf_list_node_t * nnode,struct wlan_objmgr_vdev * vdev,enum wlan_serialization_node node_type)704 bool wlan_serialization_match_cmd_vdev(qdf_list_node_t *nnode,
705 				       struct wlan_objmgr_vdev *vdev,
706 				       enum wlan_serialization_node node_type)
707 {
708 	struct wlan_serialization_command_list *cmd_list = NULL;
709 	bool match_found = false;
710 
711 	if (node_type == WLAN_SER_PDEV_NODE)
712 		cmd_list =
713 			qdf_container_of(nnode,
714 					 struct wlan_serialization_command_list,
715 					 pdev_node);
716 	else
717 		cmd_list =
718 			qdf_container_of(nnode,
719 					 struct wlan_serialization_command_list,
720 					 vdev_node);
721 
722 	if (cmd_list->cmd.vdev == vdev)
723 		match_found = true;
724 
725 	if (!match_found)
726 		ser_debug("matching cmd not found for (vdev:%pK)", vdev);
727 
728 	return match_found;
729 }
730 
wlan_serialization_match_cmd_pdev(qdf_list_node_t * nnode,struct wlan_objmgr_pdev * pdev,enum wlan_serialization_node node_type)731 bool wlan_serialization_match_cmd_pdev(qdf_list_node_t *nnode,
732 				       struct wlan_objmgr_pdev *pdev,
733 				       enum wlan_serialization_node node_type)
734 {
735 	struct wlan_serialization_command_list *cmd_list = NULL;
736 	bool match_found = false;
737 	struct wlan_objmgr_pdev *node_pdev = NULL;
738 
739 	if (node_type == WLAN_SER_PDEV_NODE)
740 		cmd_list =
741 			qdf_container_of(nnode,
742 					 struct wlan_serialization_command_list,
743 					 pdev_node);
744 	else
745 		cmd_list =
746 			qdf_container_of(nnode,
747 					 struct wlan_serialization_command_list,
748 					 vdev_node);
749 
750 	node_pdev = wlan_vdev_get_pdev(cmd_list->cmd.vdev);
751 	if (node_pdev == pdev)
752 		match_found = true;
753 
754 	return match_found;
755 }
756 
wlan_serialization_match_cmd_blocking(qdf_list_node_t * nnode,enum wlan_serialization_node node_type)757 bool wlan_serialization_match_cmd_blocking(
758 		qdf_list_node_t *nnode,
759 		enum wlan_serialization_node node_type)
760 {
761 	struct wlan_serialization_command_list *cmd_list = NULL;
762 	bool match_found = false;
763 
764 	if (node_type == WLAN_SER_PDEV_NODE)
765 		cmd_list =
766 			qdf_container_of(nnode,
767 					 struct wlan_serialization_command_list,
768 					 pdev_node);
769 	else
770 		cmd_list =
771 			qdf_container_of(nnode,
772 					 struct wlan_serialization_command_list,
773 					 vdev_node);
774 
775 	if (cmd_list->cmd.is_blocking)
776 		match_found = true;
777 
778 	return match_found;
779 }
780 
781 qdf_list_node_t *
wlan_serialization_find_cmd(qdf_list_t * queue,enum wlan_serialization_match_type match_type,struct wlan_serialization_command * cmd,enum wlan_serialization_cmd_type cmd_type,struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_vdev * vdev,enum wlan_serialization_node node_type)782 wlan_serialization_find_cmd(qdf_list_t *queue,
783 			    enum wlan_serialization_match_type match_type,
784 			    struct wlan_serialization_command *cmd,
785 			    enum wlan_serialization_cmd_type cmd_type,
786 			    struct wlan_objmgr_pdev *pdev,
787 			    struct wlan_objmgr_vdev *vdev,
788 			    enum wlan_serialization_node node_type)
789 {
790 	qdf_list_node_t *cmd_node = NULL;
791 	uint32_t queuelen;
792 	qdf_list_node_t *nnode = NULL;
793 	QDF_STATUS status;
794 	bool node_found = 0;
795 
796 	queuelen = wlan_serialization_list_size(queue);
797 
798 	if (!queuelen)
799 		goto error;
800 
801 	while (queuelen--) {
802 		status = wlan_serialization_get_cmd_from_queue(queue, &nnode);
803 		if (status != QDF_STATUS_SUCCESS)
804 			break;
805 
806 		switch (match_type) {
807 		case WLAN_SER_MATCH_PDEV:
808 			if (wlan_serialization_match_cmd_pdev(
809 					nnode, pdev, WLAN_SER_PDEV_NODE))
810 				node_found = 1;
811 			break;
812 		case WLAN_SER_MATCH_VDEV:
813 			if (wlan_serialization_match_cmd_vdev(
814 					nnode, vdev, node_type))
815 				node_found = 1;
816 			break;
817 		case WLAN_SER_MATCH_CMD_TYPE_VDEV:
818 			if (wlan_serialization_match_cmd_type(
819 					nnode, cmd_type, node_type) &&
820 			    wlan_serialization_match_cmd_vdev(
821 					nnode, vdev, node_type))
822 				node_found = 1;
823 			break;
824 		case WLAN_SER_MATCH_CMD_ID_VDEV:
825 			if (wlan_serialization_match_cmd_id_type(
826 					nnode, cmd, node_type) &&
827 			    wlan_serialization_match_cmd_vdev(
828 					nnode, vdev, node_type))
829 				node_found = 1;
830 			break;
831 		default:
832 			break;
833 		}
834 
835 		if (node_found) {
836 			cmd_node = nnode;
837 			break;
838 		}
839 	}
840 error:
841 	return cmd_node;
842 }
843 
844 QDF_STATUS
wlan_serialization_acquire_lock(qdf_spinlock_t * lock)845 wlan_serialization_acquire_lock(qdf_spinlock_t *lock)
846 {
847 	qdf_spin_lock_bh(lock);
848 
849 	return QDF_STATUS_SUCCESS;
850 }
851 
852 QDF_STATUS
wlan_serialization_release_lock(qdf_spinlock_t * lock)853 wlan_serialization_release_lock(qdf_spinlock_t *lock)
854 {
855 	qdf_spin_unlock_bh(lock);
856 
857 	return QDF_STATUS_SUCCESS;
858 }
859 
860 QDF_STATUS
wlan_serialization_create_lock(qdf_spinlock_t * lock)861 wlan_serialization_create_lock(qdf_spinlock_t *lock)
862 {
863 	qdf_spinlock_create(lock);
864 
865 	return QDF_STATUS_SUCCESS;
866 }
867 
868 QDF_STATUS
wlan_serialization_destroy_lock(qdf_spinlock_t * lock)869 wlan_serialization_destroy_lock(qdf_spinlock_t *lock)
870 {
871 	qdf_spinlock_destroy(lock);
872 
873 	return QDF_STATUS_SUCCESS;
874 }
875 
wlan_serialization_any_vdev_cmd_active(struct wlan_serialization_pdev_queue * pdev_queue)876 bool wlan_serialization_any_vdev_cmd_active(
877 		struct wlan_serialization_pdev_queue *pdev_queue)
878 {
879 	uint32_t vdev_bitmap_size;
880 
881 	vdev_bitmap_size =
882 		(QDF_CHAR_BIT * sizeof(pdev_queue->vdev_active_cmd_bitmap));
883 
884 	return !qdf_bitmap_empty(pdev_queue->vdev_active_cmd_bitmap,
885 				 vdev_bitmap_size);
886 }
887