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
wlan_serialization_is_non_scan_pending_queue_empty(struct wlan_serialization_command * cmd)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
wlan_serialization_is_active_non_scan_cmd_allowed(struct wlan_serialization_command * cmd)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 
wlan_ser_add_non_scan_cmd(struct wlan_ser_pdev_obj * ser_pdev_obj,struct wlan_serialization_command_list * cmd_list,uint8_t is_cmd_for_active_queue)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
wlan_ser_move_non_scan_pending_to_active(struct wlan_ser_pdev_obj * ser_pdev_obj,struct wlan_objmgr_vdev * vdev,bool blocking_cmd_removed)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 = NULL;
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 	if (vdev) {
249 		ser_vdev_obj = wlan_serialization_get_vdev_obj(vdev);
250 		if (!ser_vdev_obj) {
251 			ser_err("Can't find ser_vdev_obj");
252 			goto error;
253 		}
254 
255 		vdev_queue =
256 			&ser_vdev_obj->vdev_q[SER_VDEV_QUEUE_COMP_NON_SCAN];
257 	}
258 
259 	wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock);
260 
261 	blocking_cmd_waiting = pdev_queue->blocking_cmd_waiting;
262 
263 	if (!blocking_cmd_removed && !blocking_cmd_waiting && vdev_queue) {
264 		pending_queue = &vdev_queue->pending_list;
265 		vdev_queue_lookup = true;
266 	} else {
267 		pending_queue = &pdev_queue->pending_list;
268 	}
269 
270 	qsize =  wlan_serialization_list_size(pending_queue);
271 	if (!qsize) {
272 		wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
273 		goto error;
274 	}
275 
276 	qdf_status = wlan_serialization_peek_front(pending_queue,
277 						   &pending_node);
278 	if (qdf_status != QDF_STATUS_SUCCESS) {
279 		ser_err("can't peek cmd");
280 		wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
281 		goto error;
282 	}
283 
284 	while (qsize--) {
285 		if (vdev_queue_lookup) {
286 			pending_cmd_list =
287 				qdf_container_of(
288 				pending_node,
289 				struct wlan_serialization_command_list,
290 				vdev_node);
291 		} else {
292 			pending_cmd_list =
293 				qdf_container_of(
294 				pending_node,
295 				struct wlan_serialization_command_list,
296 				pdev_node);
297 		}
298 
299 		if (!pending_cmd_list) {
300 			wlan_serialization_release_lock(
301 				&pdev_queue->pdev_queue_lock);
302 			ser_debug(
303 				"non scan cmd cannot move frm pendin to actv");
304 			goto error;
305 		}
306 
307 		vdev_id = wlan_vdev_get_id(pending_cmd_list->cmd.vdev);
308 		vdev_cmd_active = qdf_test_bit(
309 				vdev_id, pdev_queue->vdev_active_cmd_bitmap);
310 
311 		if (!vdev_queue_lookup) {
312 			if (pending_cmd_list->cmd.is_blocking &&
313 			    wlan_serialization_any_vdev_cmd_active(
314 					pdev_queue)) {
315 				break;
316 			}
317 			/*
318 			 * For the last node we dont need the next node
319 			 */
320 			if (qsize) {
321 				qdf_status = wlan_serialization_peek_next(
322 					pending_queue,
323 					pending_node,
324 					&next_node);
325 
326 				if (qdf_status != QDF_STATUS_SUCCESS) {
327 					ser_err("can't peek cmd");
328 					break;
329 				}
330 
331 				pending_node = next_node;
332 
333 				next_cmd_list = qdf_container_of(
334 					next_node,
335 					struct wlan_serialization_command_list,
336 					pdev_node);
337 
338 				qdf_atomic_set_bit(CMD_MARKED_FOR_MOVEMENT,
339 						   &next_cmd_list->cmd_in_use);
340 			}
341 
342 			if (vdev_cmd_active) {
343 				qdf_atomic_clear_bit(CMD_MARKED_FOR_MOVEMENT,
344 						     &pending_cmd_list->cmd_in_use);
345 				continue;
346 			}
347 		} else {
348 			if (vdev_cmd_active)
349 				break;
350 
351 			if (qdf_atomic_test_bit(
352 					CMD_MARKED_FOR_MOVEMENT,
353 					&pending_cmd_list->cmd_in_use)) {
354 				break;
355 			}
356 		}
357 
358 		qdf_mem_copy(&cmd_to_remove, &pending_cmd_list->cmd,
359 			     sizeof(struct wlan_serialization_command));
360 
361 		qdf_status = wlan_ser_remove_non_scan_cmd(ser_pdev_obj,
362 							  &pending_cmd_list,
363 							  &cmd_to_remove,
364 							  false);
365 
366 		wlan_ser_update_cmd_history(
367 				pdev_queue, &pending_cmd_list->cmd,
368 				SER_PENDING_TO_ACTIVE,
369 				false, false);
370 
371 		if (QDF_STATUS_SUCCESS != qdf_status) {
372 			wlan_serialization_release_lock(
373 					&pdev_queue->pdev_queue_lock);
374 			ser_err("Can't remove cmd from pendingQ id-%d type-%d",
375 				pending_cmd_list->cmd.cmd_id,
376 				pending_cmd_list->cmd.cmd_type);
377 			QDF_ASSERT(0);
378 			status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
379 			goto error;
380 		}
381 
382 		active_cmd_list = pending_cmd_list;
383 
384 		status = wlan_ser_add_non_scan_cmd(
385 				ser_pdev_obj, active_cmd_list, true);
386 
387 		if (WLAN_SER_CMD_ACTIVE != status) {
388 			wlan_serialization_release_lock(
389 					&pdev_queue->pdev_queue_lock);
390 			ser_err("Can't move cmd to activeQ id-%d type-%d",
391 				pending_cmd_list->cmd.cmd_id,
392 				pending_cmd_list->cmd.cmd_type);
393 			wlan_serialization_insert_back(
394 				&pdev_queue->cmd_pool_list,
395 				&active_cmd_list->pdev_node);
396 			status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
397 			QDF_ASSERT(0);
398 			goto error;
399 		}
400 
401 		wlan_ser_update_cmd_history(
402 				pdev_queue, &active_cmd_list->cmd,
403 				SER_PENDING_TO_ACTIVE,
404 				true, true);
405 
406 		qdf_atomic_set_bit(CMD_MARKED_FOR_ACTIVATION,
407 				   &active_cmd_list->cmd_in_use);
408 
409 		if (active_cmd_list->cmd.is_blocking)
410 			pdev_queue->blocking_cmd_waiting--;
411 
412 		wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
413 
414 		wlan_serialization_activate_cmd(active_cmd_list, ser_pdev_obj,
415 						SER_PENDING_TO_ACTIVE);
416 
417 		wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock);
418 
419 		if (vdev_queue_lookup || pdev_queue->blocking_cmd_active)
420 			break;
421 
422 		qsize =  wlan_serialization_list_size(pending_queue);
423 		if (!qsize) {
424 			wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
425 			goto error;
426 		}
427 
428 		qdf_status = wlan_serialization_peek_front(pending_queue,
429 							   &pending_node);
430 		if (qdf_status != QDF_STATUS_SUCCESS) {
431 			ser_err("can't peek cmd");
432 			wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
433 			goto error;
434 		}
435 	}
436 
437 	wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
438 error:
439 
440 	return status;
441 }
442 
wlan_ser_remove_non_scan_cmd(struct wlan_ser_pdev_obj * ser_pdev_obj,struct wlan_serialization_command_list ** pcmd_list,struct wlan_serialization_command * cmd,uint8_t is_active_cmd)443 QDF_STATUS wlan_ser_remove_non_scan_cmd(
444 		struct wlan_ser_pdev_obj *ser_pdev_obj,
445 		struct wlan_serialization_command_list **pcmd_list,
446 		struct wlan_serialization_command *cmd,
447 		uint8_t is_active_cmd)
448 {
449 	QDF_STATUS pdev_status, vdev_status;
450 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
451 	uint32_t vdev_id;
452 	bool blocking_cmd_removed = 0;
453 	struct wlan_serialization_pdev_queue *pdev_queue;
454 
455 	vdev_status =
456 		wlan_serialization_remove_cmd_from_vdev_queue(ser_pdev_obj,
457 							      pcmd_list,
458 							      cmd,
459 							      is_active_cmd);
460 
461 	/* Here command removal can fail for 2 reasons
462 	 * 1. The cmd is not present
463 	 * 2. The command had not returned from activation
464 	 *    and will not be removed now.
465 	 *
466 	 *  In the second case, we should not flag it as error
467 	 *  since it will removed after the activation completes.
468 	 */
469 
470 	if (vdev_status != QDF_STATUS_SUCCESS) {
471 		status = vdev_status;
472 		if (vdev_status != QDF_STATUS_E_PENDING)
473 			ser_debug("Failed to remove type %d id %d from vdev queue",
474 				  cmd->cmd_type, cmd->cmd_id);
475 		goto error;
476 	}
477 
478 	pdev_status =
479 		wlan_serialization_remove_cmd_from_pdev_queue(ser_pdev_obj,
480 							      pcmd_list,
481 							      cmd,
482 							      is_active_cmd);
483 
484 	if (pdev_status != QDF_STATUS_SUCCESS) {
485 		ser_debug("Failed to remove type %d id %d from pdev active/pending queue",
486 			  cmd->cmd_type, cmd->cmd_id);
487 		goto error;
488 	}
489 
490 	if (is_active_cmd) {
491 		blocking_cmd_removed = (*pcmd_list)->cmd.is_blocking;
492 		pdev_queue = wlan_serialization_get_pdev_queue_obj(
493 				ser_pdev_obj, (*pcmd_list)->cmd.cmd_type);
494 
495 		if (blocking_cmd_removed)
496 			pdev_queue->blocking_cmd_active = 0;
497 
498 		vdev_id = wlan_vdev_get_id(cmd->vdev);
499 		qdf_clear_bit(vdev_id, pdev_queue->vdev_active_cmd_bitmap);
500 	}
501 
502 	status = QDF_STATUS_SUCCESS;
503 
504 error:
505 	return status;
506 }
507 
508 enum wlan_serialization_cmd_status
wlan_ser_cancel_non_scan_cmd(struct wlan_ser_pdev_obj * ser_pdev_obj,struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_vdev * vdev,struct wlan_serialization_command * cmd,enum wlan_serialization_cmd_type cmd_type,uint8_t is_active_queue,enum wlan_ser_cmd_attr cmd_attr)509 wlan_ser_cancel_non_scan_cmd(
510 		struct wlan_ser_pdev_obj *ser_pdev_obj,
511 		struct wlan_objmgr_pdev *pdev, struct wlan_objmgr_vdev *vdev,
512 		struct wlan_serialization_command *cmd,
513 		enum wlan_serialization_cmd_type cmd_type,
514 		uint8_t is_active_queue, enum wlan_ser_cmd_attr cmd_attr)
515 {
516 	qdf_list_t *pdev_queue;
517 	qdf_list_t *vdev_queue;
518 	struct wlan_serialization_pdev_queue *pdev_q;
519 	uint32_t qsize;
520 	uint8_t vdev_id;
521 	bool is_blocking;
522 	struct wlan_serialization_command_list *cmd_list = NULL;
523 	struct wlan_serialization_command cmd_bkup;
524 	qdf_list_node_t *nnode = NULL, *pnode = NULL;
525 	enum wlan_serialization_cmd_status status = WLAN_SER_CMD_NOT_FOUND;
526 	struct wlan_objmgr_psoc *psoc = NULL;
527 	QDF_STATUS qdf_status;
528 	QDF_STATUS pdev_status, vdev_status;
529 	struct wlan_ser_vdev_obj *ser_vdev_obj;
530 
531 	pdev_q = wlan_serialization_get_pdev_queue_obj(ser_pdev_obj, cmd_type);
532 
533 	pdev_queue = wlan_serialization_get_list_from_pdev_queue(
534 			ser_pdev_obj, cmd_type, is_active_queue);
535 
536 	if (pdev)
537 		psoc = wlan_pdev_get_psoc(pdev);
538 	else if (vdev)
539 		psoc = wlan_vdev_get_psoc(vdev);
540 	else if (cmd && cmd->vdev)
541 		psoc = wlan_vdev_get_psoc(cmd->vdev);
542 	else
543 		ser_debug("Can't find psoc");
544 
545 	wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock);
546 
547 	qsize = wlan_serialization_list_size(pdev_queue);
548 	while (!wlan_serialization_list_empty(pdev_queue) && qsize--) {
549 		if (wlan_serialization_get_cmd_from_queue(pdev_queue, &nnode)
550 		    != QDF_STATUS_SUCCESS) {
551 			ser_err("can't read cmd from queue");
552 			status = WLAN_SER_CMD_NOT_FOUND;
553 			break;
554 		}
555 		cmd_list =
556 			qdf_container_of(nnode,
557 					 struct wlan_serialization_command_list,
558 					 pdev_node);
559 		if (cmd &&
560 		    !(wlan_serialization_match_cmd_id_type(nnode, cmd,
561 							  WLAN_SER_PDEV_NODE) &&
562 		      wlan_serialization_match_cmd_vdev(nnode, cmd->vdev,
563 							WLAN_SER_PDEV_NODE))) {
564 			pnode = nnode;
565 			continue;
566 		}
567 
568 		if (vdev &&
569 		    !wlan_serialization_match_cmd_vdev(nnode,
570 						      vdev,
571 						      WLAN_SER_PDEV_NODE)) {
572 			pnode = nnode;
573 			continue;
574 		}
575 
576 		if (pdev &&
577 		    !wlan_serialization_match_cmd_pdev(nnode,
578 						       pdev,
579 						       WLAN_SER_PDEV_NODE)) {
580 			pnode = nnode;
581 			continue;
582 		}
583 
584 		if (cmd_type > WLAN_SER_CMD_NONSCAN && vdev &&
585 		    (!wlan_serialization_match_cmd_type(nnode, cmd_type,
586 							WLAN_SER_PDEV_NODE) ||
587 		    !wlan_serialization_match_cmd_vdev(nnode, vdev,
588 						       WLAN_SER_PDEV_NODE))) {
589 			pnode = nnode;
590 			continue;
591 		}
592 
593 		/*
594 		 * If a non-blocking cmd is required to be cancelled, but
595 		 * the nnode cmd is a blocking cmd then continue with the
596 		 * next command in the list else proceed with cmd cancel.
597 		 */
598 		if ((cmd_attr == WLAN_SER_CMD_ATTR_NONBLOCK) &&
599 		    wlan_serialization_match_cmd_blocking(nnode,
600 							  WLAN_SER_PDEV_NODE)) {
601 			pnode = nnode;
602 			continue;
603 		}
604 
605 		/*
606 		 * active queue can't be removed directly, requester needs to
607 		 * wait for active command response and send remove request for
608 		 * active command separately
609 		 */
610 		if (is_active_queue) {
611 			if (!psoc || !cmd_list) {
612 				ser_err("psoc:0x%pK, cmd_list:0x%pK",
613 					psoc, cmd_list);
614 				status = WLAN_SER_CMD_NOT_FOUND;
615 				break;
616 			}
617 
618 			/* Cancel request received for a cmd in active
619 			 * queue which has not been activated yet, we mark
620 			 * it as CMD_ACTIVE_MARKED_FOR_CANCEL and remove
621 			 * the cmd after activation
622 			 */
623 			if (qdf_atomic_test_bit(CMD_MARKED_FOR_ACTIVATION,
624 						&cmd_list->cmd_in_use)) {
625 				qdf_atomic_set_bit(CMD_ACTIVE_MARKED_FOR_CANCEL,
626 						   &cmd_list->cmd_in_use);
627 				status = WLAN_SER_CMD_MARKED_FOR_ACTIVATION;
628 				continue;
629 			}
630 
631 			qdf_status = wlan_serialization_find_and_stop_timer(
632 							psoc, &cmd_list->cmd,
633 							SER_CANCEL);
634 			if (QDF_IS_STATUS_ERROR(qdf_status)) {
635 				ser_err("Can't find timer for active cmd");
636 				status = WLAN_SER_CMD_NOT_FOUND;
637 				/*
638 				 * This should not happen, as an active command
639 				 * should always have the timer.
640 				 */
641 				QDF_BUG(0);
642 				break;
643 			}
644 
645 			status = WLAN_SER_CMD_IN_ACTIVE_LIST;
646 		}
647 
648 		qdf_mem_copy(&cmd_bkup, &cmd_list->cmd,
649 			     sizeof(struct wlan_serialization_command));
650 
651 		pdev_status =
652 			wlan_serialization_remove_node(pdev_queue,
653 						       &cmd_list->pdev_node);
654 
655 		ser_vdev_obj = wlan_serialization_get_vdev_obj(
656 					cmd_list->cmd.vdev);
657 
658 		vdev_queue = wlan_serialization_get_list_from_vdev_queue(
659 			ser_vdev_obj, cmd_type, is_active_queue);
660 
661 		vdev_status =
662 			wlan_serialization_remove_node(vdev_queue,
663 						       &cmd_list->vdev_node);
664 
665 		if (pdev_status != QDF_STATUS_SUCCESS ||
666 		    vdev_status != QDF_STATUS_SUCCESS) {
667 			ser_err("can't remove cmd from pdev/vdev queue");
668 			status = WLAN_SER_CMD_NOT_FOUND;
669 			break;
670 		}
671 
672 		qdf_mem_zero(&cmd_list->cmd,
673 			     sizeof(struct wlan_serialization_command));
674 		cmd_list->cmd_in_use = 0;
675 		qdf_status = wlan_serialization_insert_back(
676 			&pdev_q->cmd_pool_list,
677 			&cmd_list->pdev_node);
678 
679 		if (QDF_STATUS_SUCCESS != qdf_status) {
680 			ser_err("can't remove cmd from queue");
681 			status = WLAN_SER_CMD_NOT_FOUND;
682 			break;
683 		}
684 		nnode = pnode;
685 
686 		vdev_id = wlan_vdev_get_id(cmd_bkup.vdev);
687 		is_blocking = cmd_bkup.is_blocking;
688 
689 		wlan_ser_update_cmd_history(pdev_q, &cmd_bkup,
690 					    SER_CANCEL, false, is_active_queue);
691 
692 		wlan_serialization_release_lock(&pdev_q->pdev_queue_lock);
693 		/*
694 		 * call pending cmd's callback to notify that
695 		 * it is being removed
696 		 */
697 		if (cmd_bkup.cmd_cb) {
698 			/* caller should now do necessary clean up */
699 			ser_debug("Cancel command: type %d id %d vdev %d and Release memory",
700 				  cmd_bkup.cmd_type, cmd_bkup.cmd_id, vdev_id);
701 			cmd_bkup.cmd_cb(&cmd_bkup, WLAN_SER_CB_CANCEL_CMD);
702 			/* caller should release the memory */
703 			cmd_bkup.cmd_cb(&cmd_bkup, WLAN_SER_CB_RELEASE_MEM_CMD);
704 		}
705 
706 		wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock);
707 
708 		if (is_active_queue) {
709 			if (is_blocking)
710 				pdev_q->blocking_cmd_active = 0;
711 
712 			qdf_clear_bit(vdev_id, pdev_q->vdev_active_cmd_bitmap);
713 
714 			ser_debug("active_cmd_bitmap after resetting vdev %d",
715 				  vdev_id);
716 			ser_debug_hex(pdev_q->vdev_active_cmd_bitmap,
717 				      sizeof(pdev_q->vdev_active_cmd_bitmap));
718 
719 		} else {
720 			if (is_blocking)
721 				pdev_q->blocking_cmd_waiting--;
722 
723 			status = WLAN_SER_CMD_IN_PENDING_LIST;
724 		}
725 
726 
727 		if (!vdev && !pdev)
728 			break;
729 	}
730 
731 	wlan_serialization_release_lock(&pdev_q->pdev_queue_lock);
732 
733 	if (is_active_queue && wlan_serialization_list_empty(pdev_queue) &&
734 	    !wlan_serialization_any_vdev_cmd_active(pdev_q)) {
735 		/*
736 		 * Try to do reactive pdev pending list command to active list
737 		 * since all active list commands are already canceled and no
738 		 * active vdev commands.
739 		 */
740 		wlan_ser_move_non_scan_pending_to_active(ser_pdev_obj,
741 							 NULL, false);
742 	}
743 
744 	return status;
745 }
746 
747 bool
wlan_serialization_is_blocking_non_scan_cmd_waiting(struct wlan_objmgr_pdev * pdev)748 wlan_serialization_is_blocking_non_scan_cmd_waiting(
749 				struct wlan_objmgr_pdev *pdev)
750 {
751 	struct wlan_serialization_pdev_queue *pdev_queue;
752 	struct wlan_ser_pdev_obj *ser_pdev_obj;
753 	bool blocking_cmd_active = 0;
754 	uint8_t blocking_cmd_waiting = 0;
755 
756 	ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev);
757 
758 	pdev_queue = wlan_serialization_get_pdev_queue_obj(
759 					ser_pdev_obj,
760 					WLAN_SER_CMD_NONSCAN);
761 
762 	blocking_cmd_active = pdev_queue->blocking_cmd_active;
763 	blocking_cmd_waiting = pdev_queue->blocking_cmd_waiting;
764 
765 	if (blocking_cmd_active || blocking_cmd_waiting)
766 		return true;
767 
768 	return false;
769 }
770