xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_non_scan.c (revision 901120c066e139c7f8a2c8e4820561fdd83c67ef)
1 /*
2  * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022 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  * DOC: wlan_serialization_non_scan.c
21  * This file defines the functions which deals with
22  * serialization non scan commands.
23  */
24 
25 #include <wlan_objmgr_psoc_obj.h>
26 #include <wlan_objmgr_pdev_obj.h>
27 #include <wlan_objmgr_vdev_obj.h>
28 #include "wlan_serialization_main_i.h"
29 #include "wlan_serialization_utils_i.h"
30 #include "wlan_serialization_non_scan_i.h"
31 #include "qdf_util.h"
32 
33 bool
34 wlan_serialization_is_non_scan_pending_queue_empty(
35 		struct wlan_serialization_command *cmd)
36 {
37 	struct wlan_objmgr_vdev *vdev = NULL;
38 	struct wlan_ser_vdev_obj *ser_vdev_obj = NULL;
39 	struct wlan_serialization_vdev_queue *vdev_q;
40 	bool status = false;
41 
42 	vdev = wlan_serialization_get_vdev_from_cmd(cmd);
43 
44 	if (!vdev) {
45 		ser_err("vdev object  is invalid");
46 		goto error;
47 	}
48 
49 	ser_vdev_obj = wlan_serialization_get_vdev_obj(vdev);
50 	vdev_q = &ser_vdev_obj->vdev_q[SER_VDEV_QUEUE_COMP_NON_SCAN];
51 
52 	if (qdf_list_empty(&vdev_q->pending_list))
53 		status = true;
54 
55 error:
56 	return status;
57 }
58 
59 /**
60  * wlan_serialization_is_active_nonscan_cmd_allowed() - find if cmd allowed
61  * @pdev: pointer to pdev object
62  *
63  * This API will be called to find out if non scan cmd is allowed.
64  *
65  * Return: true or false
66  */
67 
68 bool
69 wlan_serialization_is_active_non_scan_cmd_allowed(
70 		struct wlan_serialization_command *cmd)
71 {
72 	struct wlan_serialization_pdev_queue *pdev_queue;
73 	struct wlan_ser_pdev_obj *ser_pdev_obj;
74 	unsigned long *vdev_active_cmd_bitmap;
75 	bool blocking_cmd_active = 0;
76 	uint8_t blocking_cmd_waiting = 0;
77 	bool status = false;
78 	uint32_t vdev_id;
79 
80 	ser_pdev_obj = wlan_serialization_get_pdev_obj(
81 			wlan_serialization_get_pdev_from_cmd(cmd));
82 
83 	pdev_queue = wlan_serialization_get_pdev_queue_obj(ser_pdev_obj,
84 							   cmd->cmd_type);
85 
86 	vdev_active_cmd_bitmap = pdev_queue->vdev_active_cmd_bitmap;
87 
88 	blocking_cmd_active = pdev_queue->blocking_cmd_active;
89 	blocking_cmd_waiting = pdev_queue->blocking_cmd_waiting;
90 
91 	/*
92 	 * Command is blocking
93 	 */
94 	if (cmd->is_blocking) {
95 		/*
96 		 * For blocking commands, no other
97 		 * commands from any vdev should be active
98 		 */
99 
100 		if (wlan_serialization_any_vdev_cmd_active(pdev_queue)) {
101 			status = false;
102 			pdev_queue->blocking_cmd_waiting++;
103 		} else {
104 			status = true;
105 		}
106 	} else {
107 		/*
108 		 * Command is non blocking
109 		 * For activating non blocking commands, if there any blocking
110 		 * commands, waiting or active, put it to pending queue
111 		 */
112 		if (blocking_cmd_active || blocking_cmd_waiting) {
113 			status = false;
114 		} else {
115 		/*
116 		 * For non blocking command, and no blocking commands
117 		 * waiting or active, check if a cmd for that vdev is active
118 		 * If not active, put to active else pending queue
119 		 */
120 			vdev_id = wlan_vdev_get_id(cmd->vdev);
121 			status = qdf_test_bit(vdev_id, vdev_active_cmd_bitmap)
122 						? false : true;
123 
124 			ser_debug_hex(
125 				vdev_active_cmd_bitmap,
126 				sizeof(pdev_queue->vdev_active_cmd_bitmap));
127 
128 		}
129 	}
130 	return status;
131 }
132 
133 enum wlan_serialization_status wlan_ser_add_non_scan_cmd(
134 		struct wlan_ser_pdev_obj *ser_pdev_obj,
135 		struct wlan_serialization_command_list *cmd_list,
136 		uint8_t is_cmd_for_active_queue)
137 {
138 	enum wlan_serialization_status pdev_status, vdev_status;
139 	enum wlan_serialization_status status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
140 	struct wlan_serialization_command_list *pcmd_list;
141 	uint8_t vdev_id;
142 	struct wlan_serialization_pdev_queue *pdev_queue;
143 
144 	vdev_status = wlan_serialization_add_cmd_to_vdev_queue(
145 			ser_pdev_obj, cmd_list, is_cmd_for_active_queue);
146 
147 	if (vdev_status == WLAN_SER_CMD_DENIED_LIST_FULL) {
148 		ser_err_rl("List is full cannot add type %d cmd id %d",
149 			   cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id);
150 		status = vdev_status;
151 		goto vdev_error;
152 	}
153 
154 	if (is_cmd_for_active_queue) {
155 		if (vdev_status != WLAN_SER_CMD_ACTIVE) {
156 			ser_err("Failed to add type %d cmd id %d to vdev active queue",
157 				cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id);
158 			QDF_ASSERT(0);
159 			goto vdev_error;
160 		}
161 	} else {
162 		if (vdev_status != WLAN_SER_CMD_PENDING) {
163 			ser_err("Failed to add type %d cmd id %d to vdev pending queue",
164 				cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id);
165 			QDF_ASSERT(0);
166 			goto vdev_error;
167 		}
168 	}
169 
170 	pdev_status = wlan_serialization_add_cmd_to_pdev_queue(
171 			ser_pdev_obj, cmd_list, is_cmd_for_active_queue);
172 
173 	if (pdev_status == WLAN_SER_CMD_DENIED_LIST_FULL) {
174 		ser_err_rl("pdev List is full cannot add type %d cmd id %d",
175 			   cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id);
176 		status = pdev_status;
177 		goto pdev_error;
178 	}
179 
180 	if (is_cmd_for_active_queue) {
181 		if (pdev_status != WLAN_SER_CMD_ACTIVE) {
182 			ser_err("Failed to add type %d cmd id %d to pdev active queue",
183 				cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id);
184 			QDF_ASSERT(0);
185 			goto pdev_error;
186 		}
187 	} else {
188 		if (pdev_status != WLAN_SER_CMD_PENDING) {
189 			ser_err("Failed to add type %d cmd id %d to pdev pending queue",
190 				cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id);
191 			QDF_ASSERT(0);
192 			goto pdev_error;
193 		}
194 	}
195 pdev_error:
196 	/*
197 	 * If cmd added to vdev queue, but failed while
198 	 * adding to pdev queue, remove cmd from vdev queue as well
199 	 */
200 	if (pdev_status != vdev_status) {
201 		wlan_serialization_remove_cmd_from_vdev_queue(
202 			ser_pdev_obj, &pcmd_list,
203 			&cmd_list->cmd,
204 			is_cmd_for_active_queue);
205 		goto vdev_error;
206 	} else {
207 		status = pdev_status;
208 	}
209 
210 	if (is_cmd_for_active_queue) {
211 		pdev_queue = wlan_serialization_get_pdev_queue_obj(
212 				ser_pdev_obj, cmd_list->cmd.cmd_type);
213 		vdev_id = wlan_vdev_get_id(cmd_list->cmd.vdev);
214 		qdf_set_bit(vdev_id, pdev_queue->vdev_active_cmd_bitmap);
215 
216 		if (cmd_list->cmd.is_blocking)
217 			pdev_queue->blocking_cmd_active = 1;
218 	}
219 
220 vdev_error:
221 	return status;
222 }
223 
224 enum wlan_serialization_status
225 wlan_ser_move_non_scan_pending_to_active(
226 		struct wlan_ser_pdev_obj *ser_pdev_obj,
227 		struct wlan_objmgr_vdev *vdev,
228 		bool blocking_cmd_removed)
229 {
230 	struct wlan_serialization_command_list *pending_cmd_list = NULL;
231 	struct wlan_serialization_command_list *next_cmd_list = NULL;
232 	struct wlan_serialization_command_list *active_cmd_list;
233 	struct wlan_serialization_command cmd_to_remove;
234 	enum wlan_serialization_status status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
235 	struct wlan_serialization_pdev_queue *pdev_queue;
236 	struct wlan_serialization_vdev_queue *vdev_queue;
237 
238 	struct wlan_ser_vdev_obj *ser_vdev_obj;
239 
240 	qdf_list_t *pending_queue;
241 	qdf_list_node_t *pending_node = NULL;
242 	qdf_list_node_t *next_node = NULL;
243 	QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
244 	uint32_t blocking_cmd_waiting = 0;
245 	uint32_t vdev_id;
246 	uint32_t qsize;
247 	bool vdev_cmd_active = 0;
248 	bool vdev_queue_lookup = false;
249 
250 	if (!ser_pdev_obj) {
251 		ser_err("Can't find ser_pdev_obj");
252 		goto error;
253 	}
254 
255 	pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN];
256 
257 	ser_vdev_obj = wlan_serialization_get_vdev_obj(vdev);
258 
259 	if (!ser_vdev_obj) {
260 		ser_err("Can't find ser_vdev_obj");
261 		goto error;
262 	}
263 
264 	vdev_queue = &ser_vdev_obj->vdev_q[SER_VDEV_QUEUE_COMP_NON_SCAN];
265 
266 	wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock);
267 
268 	blocking_cmd_waiting = pdev_queue->blocking_cmd_waiting;
269 
270 	if (!blocking_cmd_removed && !blocking_cmd_waiting) {
271 		pending_queue = &vdev_queue->pending_list;
272 		vdev_queue_lookup = true;
273 	} else {
274 		pending_queue = &pdev_queue->pending_list;
275 	}
276 
277 	qsize =  wlan_serialization_list_size(pending_queue);
278 	if (!qsize) {
279 		wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
280 		goto error;
281 	}
282 
283 	qdf_status = wlan_serialization_peek_front(pending_queue,
284 						   &pending_node);
285 	if (qdf_status != QDF_STATUS_SUCCESS) {
286 		ser_err("can't peek cmd");
287 		wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
288 		goto error;
289 	}
290 
291 	while (qsize--) {
292 		if (vdev_queue_lookup) {
293 			pending_cmd_list =
294 				qdf_container_of(
295 				pending_node,
296 				struct wlan_serialization_command_list,
297 				vdev_node);
298 		} else {
299 			pending_cmd_list =
300 				qdf_container_of(
301 				pending_node,
302 				struct wlan_serialization_command_list,
303 				pdev_node);
304 		}
305 
306 		if (!pending_cmd_list) {
307 			wlan_serialization_release_lock(
308 				&pdev_queue->pdev_queue_lock);
309 			ser_debug(
310 				"non scan cmd cannot move frm pendin to actv");
311 			goto error;
312 		}
313 
314 		vdev_id = wlan_vdev_get_id(pending_cmd_list->cmd.vdev);
315 		vdev_cmd_active = qdf_test_bit(
316 				vdev_id, pdev_queue->vdev_active_cmd_bitmap);
317 
318 		if (!vdev_queue_lookup) {
319 			if (pending_cmd_list->cmd.is_blocking &&
320 			    wlan_serialization_any_vdev_cmd_active(
321 					pdev_queue)) {
322 				break;
323 			}
324 			/*
325 			 * For the last node we dont need the next node
326 			 */
327 			if (qsize) {
328 				qdf_status = wlan_serialization_peek_next(
329 					pending_queue,
330 					pending_node,
331 					&next_node);
332 
333 				if (qdf_status != QDF_STATUS_SUCCESS) {
334 					ser_err("can't peek cmd");
335 					break;
336 				}
337 
338 				pending_node = next_node;
339 
340 				next_cmd_list = qdf_container_of(
341 					next_node,
342 					struct wlan_serialization_command_list,
343 					pdev_node);
344 
345 				qdf_atomic_set_bit(CMD_MARKED_FOR_MOVEMENT,
346 						   &next_cmd_list->cmd_in_use);
347 			}
348 
349 			if (vdev_cmd_active) {
350 				qdf_atomic_clear_bit(CMD_MARKED_FOR_MOVEMENT,
351 						     &pending_cmd_list->cmd_in_use);
352 				continue;
353 			}
354 		} else {
355 			if (vdev_cmd_active)
356 				break;
357 
358 			if (qdf_atomic_test_bit(
359 					CMD_MARKED_FOR_MOVEMENT,
360 					&pending_cmd_list->cmd_in_use)) {
361 				break;
362 			}
363 		}
364 
365 		qdf_mem_copy(&cmd_to_remove, &pending_cmd_list->cmd,
366 			     sizeof(struct wlan_serialization_command));
367 
368 		qdf_status = wlan_ser_remove_non_scan_cmd(ser_pdev_obj,
369 							  &pending_cmd_list,
370 							  &cmd_to_remove,
371 							  false);
372 
373 		wlan_ser_update_cmd_history(
374 				pdev_queue, &pending_cmd_list->cmd,
375 				SER_PENDING_TO_ACTIVE,
376 				false, false);
377 
378 		if (QDF_STATUS_SUCCESS != qdf_status) {
379 			wlan_serialization_release_lock(
380 					&pdev_queue->pdev_queue_lock);
381 			ser_err("Can't remove cmd from pendingQ id-%d type-%d",
382 				pending_cmd_list->cmd.cmd_id,
383 				pending_cmd_list->cmd.cmd_type);
384 			QDF_ASSERT(0);
385 			status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
386 			goto error;
387 		}
388 
389 		active_cmd_list = pending_cmd_list;
390 
391 		status = wlan_ser_add_non_scan_cmd(
392 				ser_pdev_obj, active_cmd_list, true);
393 
394 		if (WLAN_SER_CMD_ACTIVE != status) {
395 			wlan_serialization_release_lock(
396 					&pdev_queue->pdev_queue_lock);
397 			ser_err("Can't move cmd to activeQ id-%d type-%d",
398 				pending_cmd_list->cmd.cmd_id,
399 				pending_cmd_list->cmd.cmd_type);
400 			wlan_serialization_insert_back(
401 				&pdev_queue->cmd_pool_list,
402 				&active_cmd_list->pdev_node);
403 			status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
404 			QDF_ASSERT(0);
405 			goto error;
406 		}
407 
408 		wlan_ser_update_cmd_history(
409 				pdev_queue, &active_cmd_list->cmd,
410 				SER_PENDING_TO_ACTIVE,
411 				true, true);
412 
413 		qdf_atomic_set_bit(CMD_MARKED_FOR_ACTIVATION,
414 				   &active_cmd_list->cmd_in_use);
415 
416 		if (active_cmd_list->cmd.is_blocking)
417 			pdev_queue->blocking_cmd_waiting--;
418 
419 		wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
420 
421 		wlan_serialization_activate_cmd(active_cmd_list, ser_pdev_obj,
422 						SER_PENDING_TO_ACTIVE);
423 
424 		wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock);
425 
426 		if (vdev_queue_lookup || pdev_queue->blocking_cmd_active)
427 			break;
428 
429 		qsize =  wlan_serialization_list_size(pending_queue);
430 		if (!qsize) {
431 			wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
432 			goto error;
433 		}
434 
435 		qdf_status = wlan_serialization_peek_front(pending_queue,
436 							   &pending_node);
437 		if (qdf_status != QDF_STATUS_SUCCESS) {
438 			ser_err("can't peek cmd");
439 			wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
440 			goto error;
441 		}
442 	}
443 
444 	wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
445 error:
446 
447 	return status;
448 }
449 
450 QDF_STATUS wlan_ser_remove_non_scan_cmd(
451 		struct wlan_ser_pdev_obj *ser_pdev_obj,
452 		struct wlan_serialization_command_list **pcmd_list,
453 		struct wlan_serialization_command *cmd,
454 		uint8_t is_active_cmd)
455 {
456 	QDF_STATUS pdev_status, vdev_status;
457 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
458 	uint32_t vdev_id;
459 	bool blocking_cmd_removed = 0;
460 	struct wlan_serialization_pdev_queue *pdev_queue;
461 
462 	vdev_status =
463 		wlan_serialization_remove_cmd_from_vdev_queue(ser_pdev_obj,
464 							      pcmd_list,
465 							      cmd,
466 							      is_active_cmd);
467 
468 	/* Here command removal can fail for 2 reasons
469 	 * 1. The cmd is not present
470 	 * 2. The command had not returned from activation
471 	 *    and will not be removed now.
472 	 *
473 	 *  In the second case, we should not flag it as error
474 	 *  since it will removed after the activation completes.
475 	 */
476 
477 	if (vdev_status != QDF_STATUS_SUCCESS) {
478 		status = vdev_status;
479 		if (vdev_status != QDF_STATUS_E_PENDING)
480 			ser_debug("Failed to remove type %d id %d from vdev queue",
481 				  cmd->cmd_type, cmd->cmd_id);
482 		goto error;
483 	}
484 
485 	pdev_status =
486 		wlan_serialization_remove_cmd_from_pdev_queue(ser_pdev_obj,
487 							      pcmd_list,
488 							      cmd,
489 							      is_active_cmd);
490 
491 	if (pdev_status != QDF_STATUS_SUCCESS) {
492 		ser_debug("Failed to remove type %d id %d from pdev active/pending queue",
493 			  cmd->cmd_type, cmd->cmd_id);
494 		goto error;
495 	}
496 
497 	if (is_active_cmd) {
498 		blocking_cmd_removed = (*pcmd_list)->cmd.is_blocking;
499 		pdev_queue = wlan_serialization_get_pdev_queue_obj(
500 				ser_pdev_obj, (*pcmd_list)->cmd.cmd_type);
501 
502 		if (blocking_cmd_removed)
503 			pdev_queue->blocking_cmd_active = 0;
504 
505 		vdev_id = wlan_vdev_get_id(cmd->vdev);
506 		qdf_clear_bit(vdev_id, pdev_queue->vdev_active_cmd_bitmap);
507 	}
508 
509 	status = QDF_STATUS_SUCCESS;
510 
511 error:
512 	return status;
513 }
514 
515 enum wlan_serialization_cmd_status
516 wlan_ser_cancel_non_scan_cmd(
517 		struct wlan_ser_pdev_obj *ser_pdev_obj,
518 		struct wlan_objmgr_pdev *pdev, struct wlan_objmgr_vdev *vdev,
519 		struct wlan_serialization_command *cmd,
520 		enum wlan_serialization_cmd_type cmd_type,
521 		uint8_t is_active_queue, enum wlan_ser_cmd_attr cmd_attr)
522 {
523 	qdf_list_t *pdev_queue;
524 	qdf_list_t *vdev_queue;
525 	struct wlan_serialization_pdev_queue *pdev_q;
526 	uint32_t qsize;
527 	uint8_t vdev_id;
528 	bool is_blocking;
529 	struct wlan_serialization_command_list *cmd_list = NULL;
530 	struct wlan_serialization_command cmd_bkup;
531 	qdf_list_node_t *nnode = NULL, *pnode = NULL;
532 	enum wlan_serialization_cmd_status status = WLAN_SER_CMD_NOT_FOUND;
533 	struct wlan_objmgr_psoc *psoc = NULL;
534 	QDF_STATUS qdf_status;
535 	QDF_STATUS pdev_status, vdev_status;
536 	struct wlan_ser_vdev_obj *ser_vdev_obj;
537 
538 	pdev_q = wlan_serialization_get_pdev_queue_obj(ser_pdev_obj, cmd_type);
539 
540 	pdev_queue = wlan_serialization_get_list_from_pdev_queue(
541 			ser_pdev_obj, cmd_type, is_active_queue);
542 
543 	if (pdev)
544 		psoc = wlan_pdev_get_psoc(pdev);
545 	else if (vdev)
546 		psoc = wlan_vdev_get_psoc(vdev);
547 	else if (cmd && cmd->vdev)
548 		psoc = wlan_vdev_get_psoc(cmd->vdev);
549 	else
550 		ser_debug("Can't find psoc");
551 
552 	wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock);
553 
554 	qsize = wlan_serialization_list_size(pdev_queue);
555 	while (!wlan_serialization_list_empty(pdev_queue) && qsize--) {
556 		if (wlan_serialization_get_cmd_from_queue(pdev_queue, &nnode)
557 		    != QDF_STATUS_SUCCESS) {
558 			ser_err("can't read cmd from queue");
559 			status = WLAN_SER_CMD_NOT_FOUND;
560 			break;
561 		}
562 		cmd_list =
563 			qdf_container_of(nnode,
564 					 struct wlan_serialization_command_list,
565 					 pdev_node);
566 		if (cmd &&
567 		    !(wlan_serialization_match_cmd_id_type(nnode, cmd,
568 							  WLAN_SER_PDEV_NODE) &&
569 		      wlan_serialization_match_cmd_vdev(nnode, cmd->vdev,
570 							WLAN_SER_PDEV_NODE))) {
571 			pnode = nnode;
572 			continue;
573 		}
574 
575 		if (vdev &&
576 		    !wlan_serialization_match_cmd_vdev(nnode,
577 						      vdev,
578 						      WLAN_SER_PDEV_NODE)) {
579 			pnode = nnode;
580 			continue;
581 		}
582 
583 		if (pdev &&
584 		    !wlan_serialization_match_cmd_pdev(nnode,
585 						       pdev,
586 						       WLAN_SER_PDEV_NODE)) {
587 			pnode = nnode;
588 			continue;
589 		}
590 
591 		if (cmd_type > WLAN_SER_CMD_NONSCAN && vdev &&
592 		    (!wlan_serialization_match_cmd_type(nnode, cmd_type,
593 							WLAN_SER_PDEV_NODE) ||
594 		    !wlan_serialization_match_cmd_vdev(nnode, vdev,
595 						       WLAN_SER_PDEV_NODE))) {
596 			pnode = nnode;
597 			continue;
598 		}
599 
600 		/*
601 		 * If a non-blocking cmd is required to be cancelled, but
602 		 * the nnode cmd is a blocking cmd then continue with the
603 		 * next command in the list else proceed with cmd cancel.
604 		 */
605 		if ((cmd_attr == WLAN_SER_CMD_ATTR_NONBLOCK) &&
606 		    wlan_serialization_match_cmd_blocking(nnode,
607 							  WLAN_SER_PDEV_NODE)) {
608 			pnode = nnode;
609 			continue;
610 		}
611 
612 		/*
613 		 * active queue can't be removed directly, requester needs to
614 		 * wait for active command response and send remove request for
615 		 * active command separately
616 		 */
617 		if (is_active_queue) {
618 			if (!psoc || !cmd_list) {
619 				ser_err("psoc:0x%pK, cmd_list:0x%pK",
620 					psoc, cmd_list);
621 				status = WLAN_SER_CMD_NOT_FOUND;
622 				break;
623 			}
624 
625 			/* Cancel request received for a cmd in active
626 			 * queue which has not been activated yet, we mark
627 			 * it as CMD_ACTIVE_MARKED_FOR_CANCEL and remove
628 			 * the cmd after activation
629 			 */
630 			if (qdf_atomic_test_bit(CMD_MARKED_FOR_ACTIVATION,
631 						&cmd_list->cmd_in_use)) {
632 				qdf_atomic_set_bit(CMD_ACTIVE_MARKED_FOR_CANCEL,
633 						   &cmd_list->cmd_in_use);
634 				status = WLAN_SER_CMD_MARKED_FOR_ACTIVATION;
635 				continue;
636 			}
637 
638 			qdf_status = wlan_serialization_find_and_stop_timer(
639 							psoc, &cmd_list->cmd,
640 							SER_CANCEL);
641 			if (QDF_IS_STATUS_ERROR(qdf_status)) {
642 				ser_err("Can't find timer for active cmd");
643 				status = WLAN_SER_CMD_NOT_FOUND;
644 				/*
645 				 * This should not happen, as an active command
646 				 * should always have the timer.
647 				 */
648 				QDF_BUG(0);
649 				break;
650 			}
651 
652 			status = WLAN_SER_CMD_IN_ACTIVE_LIST;
653 		}
654 
655 		qdf_mem_copy(&cmd_bkup, &cmd_list->cmd,
656 			     sizeof(struct wlan_serialization_command));
657 
658 		pdev_status =
659 			wlan_serialization_remove_node(pdev_queue,
660 						       &cmd_list->pdev_node);
661 
662 		ser_vdev_obj = wlan_serialization_get_vdev_obj(
663 					cmd_list->cmd.vdev);
664 
665 		vdev_queue = wlan_serialization_get_list_from_vdev_queue(
666 			ser_vdev_obj, cmd_type, is_active_queue);
667 
668 		vdev_status =
669 			wlan_serialization_remove_node(vdev_queue,
670 						       &cmd_list->vdev_node);
671 
672 		if (pdev_status != QDF_STATUS_SUCCESS ||
673 		    vdev_status != QDF_STATUS_SUCCESS) {
674 			ser_err("can't remove cmd from pdev/vdev queue");
675 			status = WLAN_SER_CMD_NOT_FOUND;
676 			break;
677 		}
678 
679 		qdf_mem_zero(&cmd_list->cmd,
680 			     sizeof(struct wlan_serialization_command));
681 		cmd_list->cmd_in_use = 0;
682 		qdf_status = wlan_serialization_insert_back(
683 			&pdev_q->cmd_pool_list,
684 			&cmd_list->pdev_node);
685 
686 		if (QDF_STATUS_SUCCESS != qdf_status) {
687 			ser_err("can't remove cmd from queue");
688 			status = WLAN_SER_CMD_NOT_FOUND;
689 			break;
690 		}
691 		nnode = pnode;
692 
693 		vdev_id = wlan_vdev_get_id(cmd_bkup.vdev);
694 		is_blocking = cmd_bkup.is_blocking;
695 
696 		wlan_ser_update_cmd_history(pdev_q, &cmd_bkup,
697 					    SER_CANCEL, false, is_active_queue);
698 
699 		wlan_serialization_release_lock(&pdev_q->pdev_queue_lock);
700 		/*
701 		 * call pending cmd's callback to notify that
702 		 * it is being removed
703 		 */
704 		if (cmd_bkup.cmd_cb) {
705 			/* caller should now do necessary clean up */
706 			ser_debug("Cancel command: type %d id %d vdev %d and Release memory",
707 				  cmd_bkup.cmd_type, cmd_bkup.cmd_id, vdev_id);
708 			cmd_bkup.cmd_cb(&cmd_bkup, WLAN_SER_CB_CANCEL_CMD);
709 			/* caller should release the memory */
710 			cmd_bkup.cmd_cb(&cmd_bkup, WLAN_SER_CB_RELEASE_MEM_CMD);
711 		}
712 
713 		wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock);
714 
715 		if (is_active_queue) {
716 			if (is_blocking)
717 				pdev_q->blocking_cmd_active = 0;
718 
719 			qdf_clear_bit(vdev_id, pdev_q->vdev_active_cmd_bitmap);
720 
721 			ser_debug("active_cmd_bitmap after resetting vdev %d",
722 				  vdev_id);
723 			ser_debug_hex(pdev_q->vdev_active_cmd_bitmap,
724 				      sizeof(pdev_q->vdev_active_cmd_bitmap));
725 
726 		} else {
727 			if (is_blocking)
728 				pdev_q->blocking_cmd_waiting--;
729 
730 			status = WLAN_SER_CMD_IN_PENDING_LIST;
731 		}
732 
733 
734 		if (!vdev && !pdev)
735 			break;
736 	}
737 
738 	wlan_serialization_release_lock(&pdev_q->pdev_queue_lock);
739 
740 	return status;
741 }
742 
743 bool
744 wlan_serialization_is_blocking_non_scan_cmd_waiting(
745 				struct wlan_objmgr_pdev *pdev)
746 {
747 	struct wlan_serialization_pdev_queue *pdev_queue;
748 	struct wlan_ser_pdev_obj *ser_pdev_obj;
749 	bool blocking_cmd_active = 0;
750 	uint8_t blocking_cmd_waiting = 0;
751 
752 	ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev);
753 
754 	pdev_queue = wlan_serialization_get_pdev_queue_obj(
755 					ser_pdev_obj,
756 					WLAN_SER_CMD_NONSCAN);
757 
758 	blocking_cmd_active = pdev_queue->blocking_cmd_active;
759 	blocking_cmd_waiting = pdev_queue->blocking_cmd_waiting;
760 
761 	if (blocking_cmd_active || blocking_cmd_waiting)
762 		return true;
763 
764 	return false;
765 }
766