xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_utils.c (revision 5c57a8905ee57aab8b10cde048801372f46cc3c0)
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 cmd timeout for cmd_type[%d] vdev[%pK]",
159 			  cmd->cmd_type, cmd->vdev);
160 	if (cmd->cmd_cb)
161 		cmd->cmd_cb(cmd, WLAN_SER_CB_ACTIVE_CMD_TIMEOUT);
162 
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 	ser_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
513 					WLAN_UMAC_COMP_SERIALIZATION);
514 
515 	return ser_soc_obj;
516 }
517 
518 struct wlan_serialization_pdev_priv_obj *wlan_serialization_get_pdev_priv_obj(
519 		struct wlan_objmgr_pdev *pdev)
520 {
521 	struct wlan_serialization_pdev_priv_obj *obj;
522 	obj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
523 					WLAN_UMAC_COMP_SERIALIZATION);
524 
525 	return obj;
526 }
527 
528 struct wlan_serialization_psoc_priv_obj *
529 wlan_serialization_get_obj(struct wlan_serialization_command *cmd)
530 {
531 	struct wlan_serialization_psoc_priv_obj *ser_soc_obj;
532 	struct wlan_objmgr_psoc *psoc;
533 
534 	psoc = wlan_vdev_get_psoc(cmd->vdev);
535 	ser_soc_obj = wlan_serialization_get_psoc_priv_obj(psoc);
536 
537 	return ser_soc_obj;
538 }
539 
540 bool wlan_serialization_is_cmd_in_vdev_list(struct wlan_objmgr_vdev *vdev,
541 					     qdf_list_t *queue)
542 {
543 	uint32_t queuelen;
544 	qdf_list_node_t *nnode = NULL;
545 	struct wlan_serialization_command_list *cmd_list = NULL;
546 	QDF_STATUS status;
547 
548 	queuelen = qdf_list_size(queue);
549 	if (!queuelen) {
550 		serialization_debug("queue empty");
551 		return false;
552 	}
553 
554 	while (queuelen--) {
555 		status = wlan_serialization_get_cmd_from_queue(queue, &nnode);
556 		if (status != QDF_STATUS_SUCCESS)
557 			break;
558 		cmd_list = qdf_container_of(nnode,
559 				struct wlan_serialization_command_list, node);
560 		if (cmd_list->cmd.vdev == vdev)
561 			return true;
562 	};
563 
564 	return false;
565 }
566 
567 bool wlan_serialization_is_cmd_in_pdev_list(struct wlan_objmgr_pdev *pdev,
568 					     qdf_list_t *queue)
569 {
570 	uint32_t queuelen;
571 	qdf_list_node_t *nnode = NULL;
572 	struct wlan_objmgr_pdev *node_pdev = NULL;
573 	struct wlan_serialization_command_list *cmd_list = NULL;
574 	QDF_STATUS status;
575 
576 	queuelen = qdf_list_size(queue);
577 	if (!queuelen) {
578 		serialization_debug("queue empty");
579 		return false;
580 	}
581 
582 	while (queuelen--) {
583 		status = wlan_serialization_get_cmd_from_queue(queue, &nnode);
584 		if (status != QDF_STATUS_SUCCESS)
585 			break;
586 		cmd_list = qdf_container_of(nnode,
587 				struct wlan_serialization_command_list, node);
588 		node_pdev = wlan_vdev_get_pdev(cmd_list->cmd.vdev);
589 		if (node_pdev == pdev)
590 			return true;
591 	}
592 
593 	return false;
594 }
595 
596 enum wlan_serialization_cmd_status
597 wlan_serialization_is_cmd_in_active_pending(bool cmd_in_active,
598 					    bool cmd_in_pending)
599 {
600 	if (cmd_in_active && cmd_in_pending)
601 		return WLAN_SER_CMDS_IN_ALL_LISTS;
602 	else if (cmd_in_active)
603 		return WLAN_SER_CMD_IN_ACTIVE_LIST;
604 	else if (cmd_in_pending)
605 		return WLAN_SER_CMD_IN_PENDING_LIST;
606 	else
607 		return WLAN_SER_CMD_NOT_FOUND;
608 }
609 
610 static bool wlan_serialization_is_cmd_present_in_given_queue(qdf_list_t *queue,
611 				struct wlan_serialization_command *cmd)
612 {
613 	uint32_t qsize;
614 	QDF_STATUS status;
615 	struct wlan_serialization_command_list *cmd_list = NULL;
616 	qdf_list_node_t *nnode = NULL, *pnode = NULL;
617 	bool found = false;
618 
619 	qsize = qdf_list_size(queue);
620 	while (qsize--) {
621 		if (!cmd_list)
622 			status = qdf_list_peek_front(queue, &nnode);
623 		else
624 			status = qdf_list_peek_next(queue, pnode,
625 					&nnode);
626 
627 		if (status != QDF_STATUS_SUCCESS)
628 			break;
629 
630 		pnode = nnode;
631 		cmd_list = qdf_container_of(nnode,
632 				struct wlan_serialization_command_list, node);
633 		if ((cmd_list->cmd.cmd_id == cmd->cmd_id) &&
634 				(cmd_list->cmd.cmd_type == cmd->cmd_type) &&
635 				(cmd_list->cmd.vdev == cmd->vdev)) {
636 			found = true;
637 			break;
638 		}
639 		nnode = NULL;
640 	}
641 	return found;
642 }
643 
644 bool wlan_serialization_is_cmd_present_queue(
645 			struct wlan_serialization_command *cmd,
646 			uint8_t is_active_queue)
647 {
648 	qdf_list_t *queue;
649 	struct wlan_objmgr_pdev *pdev;
650 	struct wlan_serialization_pdev_priv_obj *ser_pdev_obj;
651 
652 	if (!cmd) {
653 		serialization_err("invalid params");
654 		return false;
655 	}
656 	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
657 	if (!pdev) {
658 		serialization_err("invalid pdev");
659 		return false;
660 	}
661 	ser_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
662 					WLAN_UMAC_COMP_SERIALIZATION);
663 	if (!ser_pdev_obj) {
664 		serialization_err("invalid ser_pdev_obj");
665 		return false;
666 	}
667 	if (!is_active_queue) {
668 		if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN)
669 			queue = &ser_pdev_obj->pending_scan_list;
670 		else
671 			queue = &ser_pdev_obj->pending_list;
672 	} else {
673 		if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN)
674 			queue = &ser_pdev_obj->active_scan_list;
675 		else
676 			queue = &ser_pdev_obj->active_list;
677 	}
678 
679 	return wlan_serialization_is_cmd_present_in_given_queue(queue, cmd);
680 }
681