xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_utils.c (revision e1d3d092f61a07549ab97f6f1f0c86554e0c642f)
1 /*
2  * Copyright (c) 2017 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  * DOC: wlan_serialization_utils.c
20  * This file defines the utility helper functions for serialization component.
21  */
22 
23 #include "wlan_serialization_utils_i.h"
24 #include "wlan_serialization_main_i.h"
25 #include "wlan_serialization_api.h"
26 #include "wlan_objmgr_vdev_obj.h"
27 #include "wlan_objmgr_pdev_obj.h"
28 #include "qdf_mc_timer.h"
29 #include "wlan_utility.h"
30 
31 QDF_STATUS
32 wlan_serialization_put_back_to_global_list(qdf_list_t *queue,
33 		struct wlan_serialization_pdev_priv_obj *ser_pdev_obj,
34 		struct wlan_serialization_command_list *cmd_list)
35 {
36 	QDF_STATUS status;
37 
38 	if (!queue || !ser_pdev_obj || !cmd_list) {
39 		serialization_err("input parameters are invalid");
40 		return QDF_STATUS_E_FAILURE;
41 	}
42 	status = qdf_list_remove_node(queue, &cmd_list->node);
43 	if (QDF_STATUS_SUCCESS != status) {
44 		serialization_err("can't remove cmd from queue");
45 		/* assert to catch any leaks */
46 		QDF_ASSERT(0);
47 		return status;
48 	}
49 	serialization_info("cmd_id-%d, cmd_type-%d", cmd_list->cmd.cmd_id,
50 				cmd_list->cmd.cmd_type);
51 	qdf_mem_zero(&cmd_list->cmd, sizeof(struct wlan_serialization_command));
52 	status = qdf_list_insert_back(&ser_pdev_obj->global_cmd_pool_list,
53 					&cmd_list->node);
54 	if (QDF_STATUS_SUCCESS != status) {
55 		serialization_err("can't put command back to global pool");
56 		QDF_ASSERT(0);
57 		return status;
58 	}
59 
60 	return status;
61 }
62 
63 struct wlan_objmgr_pdev*
64 wlan_serialization_get_pdev_from_cmd(struct wlan_serialization_command *cmd)
65 {
66 	struct wlan_objmgr_pdev *pdev = NULL;
67 
68 	if (!cmd) {
69 		serialization_err("invalid cmd");
70 		return pdev;
71 	}
72 	pdev = wlan_vdev_get_pdev(cmd->vdev);
73 
74 	return pdev;
75 }
76 
77 /**
78  * wlan_serialization_get_cmd_from_queue() - to extract command from given queue
79  * @queue: pointer to queue
80  * @nnode: next node to extract
81  *
82  * This API will try to extract node from queue which is next to prev node. If
83  * no previous node is given then take out the front node of the queue.
84  *
85  * Return: QDF_STATUS
86  */
87 QDF_STATUS wlan_serialization_get_cmd_from_queue(qdf_list_t *queue,
88 						 qdf_list_node_t **nnode)
89 {
90 	QDF_STATUS status;
91 	qdf_list_node_t *pnode;
92 
93 	pnode = *nnode;
94 	if (!pnode)
95 		status = qdf_list_peek_front(queue, nnode);
96 	else
97 		status = qdf_list_peek_next(queue, pnode, nnode);
98 
99 	if (status != QDF_STATUS_SUCCESS) {
100 		serialization_err("can't get next node from queue");
101 		return status;
102 	}
103 	return QDF_STATUS_SUCCESS;
104 }
105 
106 /**
107  * wlan_serialization_timer_destroy() - destroys the timer
108  * @ser_timer: pointer to particular timer
109  *
110  * This API destroys the memory allocated by timer and assigns cmd member of
111  * that timer structure to NULL
112  *
113  * Return: QDF_STATUS
114  */
115 static QDF_STATUS wlan_serialization_timer_destroy(
116 		struct wlan_serialization_timer *ser_timer)
117 {
118 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
119 
120 	if (!ser_timer || !ser_timer->cmd) {
121 		serialization_debug("Invalid ser_timer");
122 		return status;
123 	}
124 	status = qdf_mc_timer_destroy(&ser_timer->timer);
125 	if (!QDF_IS_STATUS_SUCCESS(status)) {
126 		serialization_err("Failed to destroy timer for cmd_id[%d]",
127 				ser_timer->cmd->cmd_id);
128 		QDF_ASSERT(0);
129 		return status;
130 	}
131 	ser_timer->cmd = NULL;
132 
133 	return status;
134 }
135 
136 /**
137  * wlan_serialization_generic_timer_callback() - timer callback when timer fire
138  * @arg: argument that timer passes to this callback
139  *
140  * All the timers in serialization module calls this callback when they fire,
141  * and this API in turn calls command specific timeout callback and remove
142  * timed-out command from active queue and move any pending command to active
143  * queue of same cmd_type.
144  *
145  * Return: none
146  */
147 static void wlan_serialization_generic_timer_callback(void *arg)
148 {
149 	struct wlan_serialization_timer *timer = arg;
150 	struct wlan_serialization_command *cmd = timer->cmd;
151 
152 	if (!cmd) {
153 		serialization_err("command not found");
154 		QDF_ASSERT(0);
155 		return;
156 	}
157 
158 	serialization_err("active command timeout for cmd_id[%d]", cmd->cmd_id);
159 	if (cmd->cmd_cb)
160 		cmd->cmd_cb(cmd, WLAN_SER_CB_ACTIVE_CMD_TIMEOUT);
161 
162 	serialization_err("active command timeout for cmd_id[%d]", cmd->cmd_id);
163 	if (cmd->cmd_type >= WLAN_SER_CMD_NONSCAN)
164 		QDF_BUG(0);
165 	/*
166 	 * dequeue cmd API will cleanup and destroy the timer. If it fails to
167 	 * dequeue command then we have to destroy the timer. It will also call
168 	 * cmd callback with WLAN_SER_CB_RELEASE_MEM_CMD to free the memory.
169 	 */
170 	if (WLAN_SER_CMD_NOT_FOUND == wlan_serialization_dequeue_cmd(cmd, true))
171 		wlan_serialization_timer_destroy(timer);
172 	if (cmd->cmd_cb)
173 		cmd->cmd_cb(cmd, WLAN_SER_CB_RELEASE_MEM_CMD);
174 }
175 
176 /**
177  * wlan_serialization_stop_timer() - to stop particular timer
178  * @ser_timer: pointer to serialization timer
179  *
180  * This API stops the particular timer
181  *
182  * Return: QDF_STATUS
183  */
184 static QDF_STATUS
185 wlan_serialization_stop_timer(struct wlan_serialization_timer *ser_timer)
186 {
187 	QDF_TIMER_STATE state;
188 	QDF_STATUS status;
189 
190 	state = qdf_mc_timer_get_current_state(&ser_timer->timer);
191 	if (QDF_TIMER_STATE_RUNNING != state ||
192 			QDF_TIMER_STATE_STARTING != state) {
193 		serialization_debug("nothing to stop");
194 		wlan_serialization_timer_destroy(ser_timer);
195 		return QDF_STATUS_SUCCESS;
196 	}
197 	status = qdf_mc_timer_stop(&ser_timer->timer);
198 	if (!QDF_IS_STATUS_SUCCESS(status)) {
199 		serialization_err("Failed to stop timer");
200 		/* to catch the bug */
201 		QDF_ASSERT(0);
202 		return status;
203 	}
204 	wlan_serialization_timer_destroy(ser_timer);
205 	status = QDF_STATUS_SUCCESS;
206 }
207 
208 QDF_STATUS wlan_serialization_cleanup_all_timers(
209 			struct wlan_serialization_psoc_priv_obj *psoc_ser_obj)
210 {
211 	struct wlan_serialization_timer *ser_timer;
212 	QDF_STATUS status = QDF_STATUS_SUCCESS;
213 	uint32_t i = 0;
214 
215 	if (!psoc_ser_obj) {
216 		serialization_err("Invalid psoc_ser_obj");
217 		return QDF_STATUS_E_FAILURE;
218 	}
219 
220 	for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) {
221 		ser_timer = &psoc_ser_obj->timers[i];
222 		if (!ser_timer->cmd)
223 			continue;
224 		status = wlan_serialization_stop_timer(ser_timer);
225 		if (QDF_STATUS_SUCCESS != status) {
226 			/* lets not break the loop but report error */
227 			serialization_err("some error in stopping timer");
228 		}
229 	}
230 
231 	return status;
232 }
233 
234 QDF_STATUS
235 wlan_serialization_find_and_stop_timer(struct wlan_objmgr_psoc *psoc,
236 				       struct wlan_serialization_command *cmd)
237 {
238 	struct wlan_serialization_psoc_priv_obj *psoc_ser_obj;
239 	struct wlan_serialization_timer *ser_timer;
240 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
241 	int i = 0;
242 
243 	if (!psoc || !cmd) {
244 		serialization_err("invalid param");
245 		return status;
246 	}
247 
248 	if ((cmd->cmd_timeout_duration == 0) &&
249 		(wlan_is_emulation_platform(wlan_psoc_get_nif_phy_version(psoc)
250 	))) {
251 		serialization_err("[SCAN-EMULATION]: Not performing timer functions\n");
252 		return QDF_STATUS_SUCCESS;
253 	}
254 
255 	psoc_ser_obj = wlan_serialization_get_psoc_priv_obj(psoc);
256 	/*
257 	 * Here cmd_id and cmd_type are used to locate the timer being
258 	 * associated with command. For scan command, cmd_id is expected to
259 	 * be unique and For non-scan command, there should be only one active
260 	 * command per pdev
261 	 */
262 	for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) {
263 		ser_timer = &psoc_ser_obj->timers[i];
264 		if (!(ser_timer->cmd) ||
265 				(ser_timer->cmd->cmd_id != cmd->cmd_id) ||
266 				(ser_timer->cmd->cmd_type != cmd->cmd_type) ||
267 				(ser_timer->cmd->vdev != cmd->vdev))
268 			continue;
269 		status = wlan_serialization_stop_timer(ser_timer);
270 		if (QDF_STATUS_SUCCESS != status) {
271 			serialization_err("Failed to stop timer for cmd_id[%d]",
272 					cmd->cmd_id);
273 		}
274 		break;
275 	}
276 
277 	if (QDF_STATUS_SUCCESS != status) {
278 		serialization_err("can't find timer for cmd_type[%d]",
279 				cmd->cmd_type);
280 	}
281 	return status;
282 }
283 
284 QDF_STATUS
285 wlan_serialization_find_and_start_timer(struct wlan_objmgr_psoc *psoc,
286 					struct wlan_serialization_command *cmd)
287 {
288 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
289 	struct wlan_serialization_psoc_priv_obj *psoc_ser_obj;
290 	struct wlan_serialization_timer *ser_timer;
291 	int i = 0;
292 
293 	if (!psoc || !cmd) {
294 		serialization_err("invalid param");
295 		return status;
296 	}
297 
298 	if ((cmd->cmd_timeout_duration == 0) &&
299 		(wlan_is_emulation_platform(wlan_psoc_get_nif_phy_version(psoc)
300 	))) {
301 		serialization_err("[SCAN-EMULATION]: Not performing timer functions\n");
302 		return QDF_STATUS_SUCCESS;
303 	}
304 
305 
306 	psoc_ser_obj = wlan_serialization_get_psoc_priv_obj(psoc);
307 	for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) {
308 		/* Keep trying timer */
309 		ser_timer = &psoc_ser_obj->timers[i];
310 		if (ser_timer->cmd)
311 			continue;
312 		/* Remember timer is pointing to command */
313 		ser_timer->cmd = cmd;
314 		if (!QDF_IS_STATUS_SUCCESS(qdf_mc_timer_init(&ser_timer->timer,
315 				QDF_TIMER_TYPE_SW,
316 				wlan_serialization_generic_timer_callback,
317 				ser_timer))) {
318 			serialization_err("Failed to init timer cmdid [%d]",
319 					cmd->cmd_id);
320 			QDF_ASSERT(0);
321 			continue;
322 		}
323 		if (!QDF_IS_STATUS_SUCCESS(qdf_mc_timer_start(&ser_timer->timer,
324 						cmd->cmd_timeout_duration))) {
325 			serialization_err("Failed to start timer cmdid [%d]",
326 					cmd->cmd_id);
327 			wlan_serialization_timer_destroy(ser_timer);
328 			QDF_ASSERT(0);
329 			continue;
330 		}
331 		status = QDF_STATUS_SUCCESS;
332 		break;
333 	}
334 
335 	return status;
336 }
337 
338 /**
339  * wlan_serialization_active_scan_cmd_count_handler() - count active scan cmds
340  * @psoc: pointer to soc strucutre
341  * @obj : pointer to pdev object
342  * @arg: pointer to argument
343  *
344  * This API will be called while iterating each pdev object and it will count
345  * number of scan commands present in that pdev object's active queue. count
346  * will be updated in *arg
347  *
348  * Return: none
349  */
350 static void
351 wlan_serialization_active_scan_cmd_count_handler(struct wlan_objmgr_psoc *psoc,
352 						 void *obj, void *arg)
353 {
354 	struct wlan_objmgr_pdev *pdev = obj;
355 	struct wlan_serialization_pdev_priv_obj *ser_pdev_obj;
356 	uint32_t *count = arg;
357 
358 	if (!pdev) {
359 		serialization_err("invalid pdev");
360 		return;
361 	}
362 
363 	ser_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(
364 			pdev, WLAN_UMAC_COMP_SERIALIZATION);
365 	*count += qdf_list_size(&ser_pdev_obj->active_scan_list);
366 }
367 
368 /**
369  * wlan_serialization_is_active_scan_cmd_allowed() - find if scan cmd allowed
370  * @pdev: pointer to pdev object
371  *
372  * This API will be called to find out if active scan cmd is allowed. It has
373  * to iterate through all pdev to find out total number of active scan cmds.
374  * If total number of active scan cmds reach to allowed threshold then don't
375  * allow more scan cmd.
376  *
377  * Return: true or false
378  */
379 static bool
380 wlan_serialization_is_active_scan_cmd_allowed(struct wlan_objmgr_pdev *pdev)
381 {
382 	uint32_t count = 0;
383 	struct wlan_objmgr_psoc *psoc;
384 
385 	if (!pdev) {
386 		serialization_err("invalid pdev");
387 		return false;
388 	}
389 
390 	psoc = wlan_pdev_get_psoc(pdev);
391 
392 	if (!psoc) {
393 		serialization_err("invalid psoc");
394 		return false;
395 	}
396 
397 	wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
398 			wlan_serialization_active_scan_cmd_count_handler,
399 			&count, 1, WLAN_SERIALIZATION_ID);
400 	if (count < ucfg_scan_get_max_active_scans(psoc)) {
401 		serialization_notice("count is [%d]", count);
402 		return true;
403 	}
404 
405 	return false;
406 }
407 
408 /**
409  * wlan_serialization_is_active_nonscan_cmd_allowed() - find if cmd allowed
410  * @pdev: pointer to pdev object
411  *
412  * This API will be called to find out if non scan cmd is allowed.
413  *
414  * Return: true or false
415  */
416 static bool
417 wlan_serialization_is_active_nonscan_cmd_allowed(struct wlan_objmgr_pdev *pdev)
418 {
419 	struct wlan_serialization_pdev_priv_obj *ser_pdev_obj;
420 
421 	if (!pdev) {
422 		serialization_err("invalid pdev");
423 		return false;
424 	}
425 
426 	ser_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(
427 			pdev, WLAN_UMAC_COMP_SERIALIZATION);
428 
429 	if (!ser_pdev_obj) {
430 		serialization_err("invalid ser_pdev_obj");
431 		return false;
432 	}
433 
434 	if (qdf_list_empty(&ser_pdev_obj->active_list))
435 		return true;
436 
437 	return false;
438 }
439 
440 bool
441 wlan_serialization_is_active_cmd_allowed(struct wlan_serialization_command *cmd)
442 {
443 	struct wlan_objmgr_pdev *pdev;
444 
445 	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
446 	if (!pdev) {
447 		serialization_err("NULL pdev");
448 		return false;
449 	}
450 
451 	if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN)
452 		return wlan_serialization_is_active_scan_cmd_allowed(pdev);
453 	else
454 		return wlan_serialization_is_active_nonscan_cmd_allowed(pdev);
455 }
456 
457 QDF_STATUS wlan_serialization_validate_cmdtype(
458 		 enum wlan_serialization_cmd_type cmd_type)
459 {
460 	serialization_info("validate cmd_type:%d", cmd_type);
461 
462 	if (cmd_type < 0 || cmd_type >= WLAN_SER_CMD_MAX) {
463 		serialization_err("Invalid cmd or comp passed");
464 		return QDF_STATUS_E_INVAL;
465 	}
466 
467 	return QDF_STATUS_SUCCESS;
468 }
469 
470 QDF_STATUS wlan_serialization_validate_cmd(
471 		 enum wlan_umac_comp_id comp_id,
472 		 enum wlan_serialization_cmd_type cmd_type)
473 {
474 	serialization_info("validate cmd_type:%d, comp_id:%d",
475 			cmd_type, comp_id);
476 	if (cmd_type < 0 || comp_id < 0 ||
477 			cmd_type >= WLAN_SER_CMD_MAX ||
478 			comp_id >= WLAN_UMAC_COMP_ID_MAX) {
479 		serialization_err("Invalid cmd or comp passed");
480 		return QDF_STATUS_E_INVAL;
481 	}
482 
483 	return QDF_STATUS_SUCCESS;
484 }
485 
486 void wlan_serialization_release_list_cmds(
487 		struct wlan_serialization_pdev_priv_obj *ser_pdev_obj,
488 		qdf_list_t *list)
489 {
490 	qdf_list_node_t *node = NULL;
491 
492 	while (!qdf_list_empty(list)) {
493 		qdf_list_remove_front(list, &node);
494 		qdf_list_insert_back(&ser_pdev_obj->global_cmd_pool_list, node);
495 	}
496 
497 	return;
498 }
499 
500 void wlan_serialization_destroy_list(
501 		struct wlan_serialization_pdev_priv_obj *ser_pdev_obj,
502 		qdf_list_t *list)
503 {
504 	wlan_serialization_release_list_cmds(ser_pdev_obj, list);
505 	qdf_list_destroy(list);
506 }
507 
508 struct wlan_serialization_psoc_priv_obj *wlan_serialization_get_psoc_priv_obj(
509 		struct wlan_objmgr_psoc *psoc)
510 {
511 	struct wlan_serialization_psoc_priv_obj *ser_soc_obj;
512 	wlan_psoc_obj_lock(psoc);
513 	ser_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
514 					WLAN_UMAC_COMP_SERIALIZATION);
515 	wlan_psoc_obj_unlock(psoc);
516 
517 	return ser_soc_obj;
518 }
519 
520 struct wlan_serialization_pdev_priv_obj *wlan_serialization_get_pdev_priv_obj(
521 		struct wlan_objmgr_pdev *pdev)
522 {
523 	struct wlan_serialization_pdev_priv_obj *obj;
524 	wlan_pdev_obj_lock(pdev);
525 	obj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
526 					WLAN_UMAC_COMP_SERIALIZATION);
527 	wlan_pdev_obj_unlock(pdev);
528 
529 	return obj;
530 }
531 
532 struct wlan_serialization_psoc_priv_obj *
533 wlan_serialization_get_obj(struct wlan_serialization_command *cmd)
534 {
535 	struct wlan_serialization_psoc_priv_obj *ser_soc_obj;
536 	struct wlan_objmgr_psoc *psoc;
537 
538 	psoc = wlan_vdev_get_psoc(cmd->vdev);
539 	ser_soc_obj = wlan_serialization_get_psoc_priv_obj(psoc);
540 
541 	return ser_soc_obj;
542 }
543 
544 bool wlan_serialization_is_cmd_in_vdev_list(struct wlan_objmgr_vdev *vdev,
545 					     qdf_list_t *queue)
546 {
547 	uint32_t queuelen;
548 	qdf_list_node_t *nnode = NULL;
549 	struct wlan_serialization_command_list *cmd_list = NULL;
550 	QDF_STATUS status;
551 
552 	queuelen = qdf_list_size(queue);
553 	if (!queuelen) {
554 		serialization_debug("queue empty");
555 		return false;
556 	}
557 
558 	while (queuelen--) {
559 		status = wlan_serialization_get_cmd_from_queue(queue, &nnode);
560 		if (status != QDF_STATUS_SUCCESS)
561 			break;
562 		cmd_list = qdf_container_of(nnode,
563 				struct wlan_serialization_command_list, node);
564 		if (cmd_list->cmd.vdev == vdev)
565 			return true;
566 	};
567 
568 	return false;
569 }
570 
571 bool wlan_serialization_is_cmd_in_pdev_list(struct wlan_objmgr_pdev *pdev,
572 					     qdf_list_t *queue)
573 {
574 	uint32_t queuelen;
575 	qdf_list_node_t *nnode = NULL;
576 	struct wlan_objmgr_pdev *node_pdev = NULL;
577 	struct wlan_serialization_command_list *cmd_list = NULL;
578 	QDF_STATUS status;
579 
580 	queuelen = qdf_list_size(queue);
581 	if (!queuelen) {
582 		serialization_debug("queue empty");
583 		return false;
584 	}
585 
586 	while (queuelen--) {
587 		status = wlan_serialization_get_cmd_from_queue(queue, &nnode);
588 		if (status != QDF_STATUS_SUCCESS)
589 			break;
590 		cmd_list = qdf_container_of(nnode,
591 				struct wlan_serialization_command_list, node);
592 		node_pdev = wlan_vdev_get_pdev(cmd_list->cmd.vdev);
593 		if (node_pdev == pdev)
594 			return true;
595 	}
596 
597 	return false;
598 }
599 
600 enum wlan_serialization_cmd_status
601 wlan_serialization_is_cmd_in_active_pending(bool cmd_in_active,
602 					    bool cmd_in_pending)
603 {
604 	if (cmd_in_active && cmd_in_pending)
605 		return WLAN_SER_CMDS_IN_ALL_LISTS;
606 	else if (cmd_in_active)
607 		return WLAN_SER_CMD_IN_ACTIVE_LIST;
608 	else if (cmd_in_pending)
609 		return WLAN_SER_CMD_IN_PENDING_LIST;
610 	else
611 		return WLAN_SER_CMD_NOT_FOUND;
612 }
613 
614 static bool wlan_serialization_is_cmd_present_in_given_queue(qdf_list_t *queue,
615 				struct wlan_serialization_command *cmd)
616 {
617 	uint32_t qsize;
618 	QDF_STATUS status;
619 	struct wlan_serialization_command_list *cmd_list = NULL;
620 	qdf_list_node_t *nnode = NULL, *pnode = NULL;
621 	bool found = false;
622 
623 	qsize = qdf_list_size(queue);
624 	while (qsize--) {
625 		if (!cmd_list)
626 			status = qdf_list_peek_front(queue, &nnode);
627 		else
628 			status = qdf_list_peek_next(queue, pnode,
629 					&nnode);
630 
631 		if (status != QDF_STATUS_SUCCESS)
632 			break;
633 
634 		pnode = nnode;
635 		cmd_list = qdf_container_of(nnode,
636 				struct wlan_serialization_command_list, node);
637 		if ((cmd_list->cmd.cmd_id == cmd->cmd_id) &&
638 				(cmd_list->cmd.cmd_type == cmd->cmd_type) &&
639 				(cmd_list->cmd.vdev == cmd->vdev)) {
640 			found = true;
641 			break;
642 		}
643 		nnode = NULL;
644 	}
645 	return found;
646 }
647 
648 bool wlan_serialization_is_cmd_present_queue(
649 			struct wlan_serialization_command *cmd,
650 			uint8_t is_active_queue)
651 {
652 	qdf_list_t *queue;
653 	struct wlan_objmgr_pdev *pdev;
654 	struct wlan_serialization_pdev_priv_obj *ser_pdev_obj;
655 
656 	if (!cmd) {
657 		serialization_err("invalid params");
658 		return false;
659 	}
660 	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
661 	if (!pdev) {
662 		serialization_err("invalid pdev");
663 		return false;
664 	}
665 	ser_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
666 					WLAN_UMAC_COMP_SERIALIZATION);
667 	if (!ser_pdev_obj) {
668 		serialization_err("invalid ser_pdev_obj");
669 		return false;
670 	}
671 	if (!is_active_queue) {
672 		if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN)
673 			queue = &ser_pdev_obj->pending_scan_list;
674 		else
675 			queue = &ser_pdev_obj->pending_list;
676 	} else {
677 		if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN)
678 			queue = &ser_pdev_obj->active_scan_list;
679 		else
680 			queue = &ser_pdev_obj->active_list;
681 	}
682 
683 	return wlan_serialization_is_cmd_present_in_given_queue(queue, cmd);
684 }
685