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