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