xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_non_scan.c (revision 0626a4da6c07f30da06dd6747e8cc290a60371d8)
1 /*
2  * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 /**
19  * DOC: wlan_serialization_non_scan.c
20  * This file defines the functions which deals with
21  * serialization non scan commands.
22  */
23 
24 #include <wlan_objmgr_psoc_obj.h>
25 #include <wlan_objmgr_pdev_obj.h>
26 #include <wlan_objmgr_vdev_obj.h>
27 #include "wlan_serialization_main_i.h"
28 #include "wlan_serialization_utils_i.h"
29 #include "wlan_serialization_non_scan_i.h"
30 
31 /**
32  * wlan_serialization_is_active_nonscan_cmd_allowed() - find if cmd allowed
33  * @pdev: pointer to pdev object
34  *
35  * This API will be called to find out if non scan cmd is allowed.
36  *
37  * Return: true or false
38  */
39 bool
40 wlan_serialization_is_active_non_scan_cmd_allowed(
41 		struct wlan_serialization_command *cmd)
42 {
43 	struct wlan_serialization_pdev_queue *pdev_queue;
44 	struct wlan_ser_pdev_obj *ser_pdev_obj;
45 	uint32_t vdev_active_cmd_bitmap;
46 	bool blocking_cmd_active = 0;
47 	uint8_t blocking_cmd_waiting = 0;
48 	bool status = false;
49 	uint32_t vdev_id;
50 
51 	ser_pdev_obj = wlan_serialization_get_pdev_obj(
52 			wlan_serialization_get_pdev_from_cmd(cmd));
53 
54 	pdev_queue = wlan_serialization_get_pdev_queue_obj(ser_pdev_obj,
55 							   cmd->cmd_type);
56 
57 	vdev_active_cmd_bitmap = pdev_queue->vdev_active_cmd_bitmap;
58 	blocking_cmd_active = pdev_queue->blocking_cmd_active;
59 	blocking_cmd_waiting = pdev_queue->blocking_cmd_waiting;
60 
61 	/*
62 	 * Command is blocking
63 	 */
64 	if (cmd->is_blocking) {
65 		/*
66 		 * For blocking commands, no other
67 		 * commands from any vdev should be active
68 		 */
69 		if (vdev_active_cmd_bitmap) {
70 			status = false;
71 			pdev_queue->blocking_cmd_waiting++;
72 		} else {
73 			status = true;
74 		}
75 	} else {
76 		/*
77 		 * Command is non blocking
78 		 * For activating non blocking commands, if there any blocking
79 		 * commands, waiting or active, put it to pending queue
80 		 */
81 		if (blocking_cmd_active || blocking_cmd_waiting) {
82 			status = false;
83 		} else {
84 		/*
85 		 * For non blocking command, and no blocking commands
86 		 * waiting or active, check if a cmd for that vdev is active
87 		 * If not active, put to active else pending queue
88 		 */
89 			vdev_id = wlan_vdev_get_id(cmd->vdev);
90 			status = vdev_active_cmd_bitmap & (1 << vdev_id)
91 						? false : true;
92 		}
93 	}
94 	return status;
95 }
96 
97 enum wlan_serialization_status wlan_ser_add_non_scan_cmd(
98 		struct wlan_ser_pdev_obj *ser_pdev_obj,
99 		struct wlan_serialization_command_list *cmd_list,
100 		uint8_t is_cmd_for_active_queue)
101 {
102 	enum wlan_serialization_status pdev_status, vdev_status;
103 	enum wlan_serialization_status status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
104 	struct wlan_serialization_command_list *pcmd_list;
105 	uint8_t vdev_id;
106 	struct wlan_serialization_pdev_queue *pdev_queue;
107 
108 	ser_debug("add non scan cmd: type[%d] id[%d] prio[%d] blocking[%d]",
109 		  cmd_list->cmd.cmd_type,
110 		  cmd_list->cmd.cmd_id,
111 		  cmd_list->cmd.is_high_priority,
112 		  cmd_list->cmd.is_blocking);
113 
114 	vdev_status = wlan_serialization_add_cmd_to_vdev_queue(
115 			ser_pdev_obj, cmd_list, is_cmd_for_active_queue);
116 
117 	if (vdev_status == WLAN_SER_CMD_DENIED_LIST_FULL) {
118 		status = vdev_status;
119 		goto vdev_error;
120 	}
121 
122 	if (is_cmd_for_active_queue) {
123 		if (vdev_status != WLAN_SER_CMD_ACTIVE) {
124 			ser_err("Failed to add to vdev active queue");
125 			QDF_ASSERT(0);
126 			goto vdev_error;
127 		}
128 	} else {
129 		if (vdev_status != WLAN_SER_CMD_PENDING) {
130 			ser_err("Failed to add to vdev pending queue");
131 			QDF_ASSERT(0);
132 			goto vdev_error;
133 		}
134 	}
135 
136 	pdev_status = wlan_serialization_add_cmd_to_pdev_queue(
137 			ser_pdev_obj, cmd_list, is_cmd_for_active_queue);
138 
139 	if (pdev_status == WLAN_SER_CMD_DENIED_LIST_FULL) {
140 		status = pdev_status;
141 		goto pdev_error;
142 	}
143 
144 	if (is_cmd_for_active_queue) {
145 		if (pdev_status != WLAN_SER_CMD_ACTIVE) {
146 			ser_err("Failed to add to pdev active queue");
147 			QDF_ASSERT(0);
148 			goto pdev_error;
149 		}
150 	} else {
151 		if (pdev_status != WLAN_SER_CMD_PENDING) {
152 			ser_err("Failed to add to pdev pending queue");
153 			QDF_ASSERT(0);
154 			goto pdev_error;
155 		}
156 	}
157 pdev_error:
158 	/*
159 	 * If cmd added to vdev queue, but failed while
160 	 * adding to pdev queue, remove cmd from vdev queue as well
161 	 */
162 	if (pdev_status != vdev_status) {
163 		wlan_serialization_remove_cmd_from_vdev_queue(
164 			ser_pdev_obj, &pcmd_list,
165 			&cmd_list->cmd,
166 			is_cmd_for_active_queue);
167 	} else {
168 		status = pdev_status;
169 	}
170 
171 	if (is_cmd_for_active_queue) {
172 		pdev_queue = wlan_serialization_get_pdev_queue_obj(
173 				ser_pdev_obj, cmd_list->cmd.cmd_type);
174 		vdev_id = wlan_vdev_get_id(cmd_list->cmd.vdev);
175 		pdev_queue->vdev_active_cmd_bitmap |= (1 << vdev_id);
176 
177 		if (cmd_list->cmd.is_blocking)
178 			pdev_queue->blocking_cmd_active = 1;
179 	}
180 
181 vdev_error:
182 	return status;
183 }
184 
185 static
186 struct wlan_serialization_command_list*
187 wlan_serialization_get_next_non_scan_active_cmd(
188 		struct wlan_ser_pdev_obj *ser_pdev_obj,
189 		struct wlan_objmgr_vdev *vdev)
190 {
191 	qdf_list_t *pending_queue;
192 	qdf_list_node_t *pending_node = NULL;
193 	struct wlan_serialization_command_list *pending_cmd_list = NULL;
194 	struct wlan_ser_vdev_obj *ser_vdev_obj;
195 	struct wlan_serialization_vdev_queue *vdev_q_obj;
196 	QDF_STATUS status;
197 
198 	ser_vdev_obj = wlan_serialization_get_vdev_obj(vdev);
199 
200 	vdev_q_obj = &ser_vdev_obj->vdev_q[SER_VDEV_QUEUE_COMP_NON_SCAN];
201 	pending_queue = &vdev_q_obj->pending_list;
202 
203 	if (wlan_serialization_list_empty(pending_queue)) {
204 		ser_debug("nothing to move from pending to active queue");
205 		goto error;
206 	}
207 
208 	status = wlan_serialization_get_cmd_from_queue(pending_queue,
209 						       &pending_node);
210 
211 	if (status != QDF_STATUS_SUCCESS) {
212 		ser_err("can't read cmd from queue");
213 		pending_cmd_list = NULL;
214 		goto error;
215 	}
216 
217 	pending_cmd_list =
218 		qdf_container_of(pending_node,
219 				 struct wlan_serialization_command_list,
220 				 vdev_node);
221 
222 	if (pending_cmd_list)
223 		ser_debug("next non scan active cmd found from pending queue");
224 
225 error:
226 	return pending_cmd_list;
227 }
228 
229 enum wlan_serialization_status
230 wlan_ser_move_multiple_non_scan_pending_to_active(
231 		struct wlan_ser_pdev_obj *ser_pdev_obj)
232 {
233 	struct wlan_serialization_pdev_queue *pdev_queue;
234 	qdf_list_t *active_queue;
235 	qdf_list_t *pending_queue;
236 	qdf_list_node_t *nnode = NULL;
237 	struct wlan_serialization_command_list *pending_cmd_list;
238 	struct wlan_serialization_command_list *active_cmd_list;
239 	struct wlan_serialization_command cmd_to_remove;
240 	uint32_t blocking_cmd_waiting;
241 	uint32_t vdev_id;
242 	uint32_t qsize;
243 	bool vdev_cmd_active = 0;
244 
245 	enum wlan_serialization_status status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
246 	QDF_STATUS peek_status = QDF_STATUS_E_FAILURE;
247 	QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
248 
249 	pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN];
250 	active_queue = &pdev_queue->active_list;
251 	pending_queue = &pdev_queue->pending_list;
252 	blocking_cmd_waiting = pdev_queue->blocking_cmd_waiting;
253 
254 	qsize =  wlan_serialization_list_size(pending_queue);
255 	while (qsize--) {
256 		peek_status = wlan_serialization_get_cmd_from_queue(
257 				pending_queue, &nnode);
258 		if (peek_status != QDF_STATUS_SUCCESS) {
259 			ser_err("can't peek cmd");
260 			break;
261 		}
262 
263 		pending_cmd_list = qdf_container_of(
264 				nnode, struct wlan_serialization_command_list,
265 				pdev_node);
266 		if (!pending_cmd_list) {
267 			ser_debug(
268 				"non scan cmd cannot move from pending to active");
269 			goto error;
270 		}
271 
272 		if (pending_cmd_list->cmd.is_blocking &&
273 		    pdev_queue->vdev_active_cmd_bitmap) {
274 			break;
275 		}
276 
277 		vdev_id = wlan_vdev_get_id(pending_cmd_list->cmd.vdev);
278 		vdev_cmd_active =
279 			pdev_queue->vdev_active_cmd_bitmap & (1 << vdev_id);
280 		if (vdev_cmd_active)
281 			continue;
282 
283 		status = WLAN_SER_CMD_ACTIVE;
284 
285 		qdf_mem_copy(&cmd_to_remove, &pending_cmd_list->cmd,
286 			     sizeof(struct wlan_serialization_command));
287 
288 		qdf_status = wlan_ser_remove_non_scan_cmd(ser_pdev_obj,
289 							  &pending_cmd_list,
290 							  &cmd_to_remove,
291 							  false);
292 
293 		if (QDF_STATUS_SUCCESS != qdf_status) {
294 			ser_err("Can't remove cmd from pendingQ id-%d type-%d",
295 				pending_cmd_list->cmd.cmd_id,
296 				pending_cmd_list->cmd.cmd_type);
297 			QDF_ASSERT(0);
298 			status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
299 			goto error;
300 		}
301 
302 		active_cmd_list = pending_cmd_list;
303 
304 		status = wlan_ser_add_non_scan_cmd(
305 				ser_pdev_obj, active_cmd_list, true);
306 
307 		if (WLAN_SER_CMD_ACTIVE != status) {
308 			ser_err("Can't move cmd to activeQ id-%d type-%d",
309 				pending_cmd_list->cmd.cmd_id,
310 				pending_cmd_list->cmd.cmd_type);
311 			wlan_serialization_insert_back(
312 				&pdev_queue->cmd_pool_list,
313 				&active_cmd_list->pdev_node);
314 			status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
315 			goto error;
316 		}
317 
318 		qdf_atomic_set_bit(CMD_MARKED_FOR_ACTIVATION,
319 				   &active_cmd_list->cmd_in_use);
320 
321 		nnode = NULL;
322 		if (active_cmd_list->cmd.is_blocking)
323 			pdev_queue->blocking_cmd_waiting--;
324 
325 		if (pending_cmd_list->cmd.is_blocking)
326 			break;
327 	}
328 
329 error:
330 	return status;
331 }
332 
333 enum wlan_serialization_status
334 wlan_ser_move_non_scan_pending_to_active(
335 		struct wlan_serialization_command_list **pcmd_list,
336 		struct wlan_ser_pdev_obj *ser_pdev_obj,
337 		struct wlan_objmgr_vdev *vdev)
338 {
339 	struct wlan_serialization_command_list *pending_cmd_list;
340 	struct wlan_serialization_command_list *active_cmd_list;
341 	struct wlan_serialization_command cmd_to_remove;
342 	enum wlan_serialization_status status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
343 	QDF_STATUS qdf_status;
344 	struct wlan_serialization_pdev_queue *pdev_queue;
345 
346 	pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN];
347 
348 	ser_enter();
349 
350 	if (!ser_pdev_obj) {
351 		ser_err("Can't find ser_pdev_obj");
352 		goto error;
353 	}
354 
355 	pending_cmd_list =
356 		wlan_serialization_get_next_non_scan_active_cmd(
357 						ser_pdev_obj,
358 						vdev);
359 
360 	if (!pending_cmd_list) {
361 		ser_debug("non scan cmd cannot move from pending to active");
362 		goto error;
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, false);
371 
372 	if (QDF_STATUS_SUCCESS != qdf_status) {
373 		ser_err("Can't remove cmd from pendingQ id-%d type-%d",
374 			pending_cmd_list->cmd.cmd_id,
375 			pending_cmd_list->cmd.cmd_type);
376 		QDF_ASSERT(0);
377 		status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
378 		goto error;
379 	}
380 
381 	active_cmd_list = pending_cmd_list;
382 
383 	status = wlan_ser_add_non_scan_cmd(
384 				ser_pdev_obj, active_cmd_list, true);
385 
386 	if (WLAN_SER_CMD_ACTIVE != status) {
387 		ser_err("Can't move cmd to activeQ id-%d type-%d",
388 			pending_cmd_list->cmd.cmd_id,
389 			pending_cmd_list->cmd.cmd_type);
390 		wlan_serialization_insert_back(
391 			&pdev_queue->cmd_pool_list,
392 			&active_cmd_list->pdev_node);
393 		goto error;
394 	}
395 
396 	qdf_atomic_set_bit(CMD_MARKED_FOR_ACTIVATION,
397 			   &active_cmd_list->cmd_in_use);
398 
399 	*pcmd_list = active_cmd_list;
400 
401 error:
402 	ser_exit();
403 	return status;
404 }
405 
406 QDF_STATUS wlan_ser_remove_non_scan_cmd(
407 		struct wlan_ser_pdev_obj *ser_pdev_obj,
408 		struct wlan_serialization_command_list **pcmd_list,
409 		struct wlan_serialization_command *cmd,
410 		uint8_t is_active_cmd)
411 {
412 	QDF_STATUS pdev_status, vdev_status;
413 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
414 	uint32_t vdev_id;
415 	bool blocking_cmd_removed = 0;
416 	struct wlan_serialization_pdev_queue *pdev_queue;
417 
418 	ser_debug("remove non scan cmd: type[%d] id[%d] prio[%d] blocking[%d]",
419 		  cmd->cmd_type,
420 		  cmd->cmd_id,
421 		  cmd->is_high_priority,
422 		  cmd->is_blocking);
423 
424 	vdev_status =
425 		wlan_serialization_remove_cmd_from_vdev_queue(ser_pdev_obj,
426 							      pcmd_list,
427 							      cmd,
428 							      is_active_cmd);
429 
430 	if (vdev_status != QDF_STATUS_SUCCESS) {
431 		ser_err("Failed to remove cmd from vdev active/pending queue");
432 		goto error;
433 	}
434 
435 	pdev_status =
436 		wlan_serialization_remove_cmd_from_pdev_queue(ser_pdev_obj,
437 							      pcmd_list,
438 							      cmd,
439 							      is_active_cmd);
440 
441 	if (pdev_status != QDF_STATUS_SUCCESS) {
442 		ser_err("Failed to remove cmd from pdev active/pending queue");
443 		goto error;
444 	}
445 
446 	if (is_active_cmd) {
447 		blocking_cmd_removed = (*pcmd_list)->cmd.is_blocking;
448 		pdev_queue = wlan_serialization_get_pdev_queue_obj(
449 				ser_pdev_obj, (*pcmd_list)->cmd.cmd_type);
450 
451 		if (blocking_cmd_removed)
452 			pdev_queue->blocking_cmd_active = 0;
453 
454 		vdev_id = wlan_vdev_get_id(cmd->vdev);
455 		pdev_queue->vdev_active_cmd_bitmap &= ~(1 << vdev_id);
456 	}
457 
458 	status = QDF_STATUS_SUCCESS;
459 
460 error:
461 	return status;
462 }
463 
464 enum wlan_serialization_cmd_status
465 wlan_ser_cancel_non_scan_cmd(
466 		struct wlan_ser_pdev_obj *ser_pdev_obj,
467 		struct wlan_objmgr_pdev *pdev, struct wlan_objmgr_vdev *vdev,
468 		struct wlan_serialization_command *cmd,
469 		enum wlan_serialization_cmd_type cmd_type,
470 		uint8_t is_active_queue)
471 {
472 	qdf_list_t *pdev_queue;
473 	qdf_list_t *vdev_queue;
474 	struct wlan_serialization_pdev_queue *pdev_q;
475 	uint32_t qsize;
476 	struct wlan_serialization_command_list *cmd_list = NULL;
477 	struct wlan_serialization_command cmd_bkup;
478 	qdf_list_node_t *nnode = NULL, *pnode = NULL;
479 	enum wlan_serialization_cmd_status status = WLAN_SER_CMD_NOT_FOUND;
480 	struct wlan_objmgr_psoc *psoc = NULL;
481 	QDF_STATUS qdf_status;
482 	QDF_STATUS pdev_status, vdev_status;
483 	struct wlan_ser_vdev_obj *ser_vdev_obj;
484 
485 	ser_enter();
486 
487 	pdev_q = wlan_serialization_get_pdev_queue_obj(ser_pdev_obj, cmd_type);
488 
489 	pdev_queue = wlan_serialization_get_list_from_pdev_queue(
490 			ser_pdev_obj, cmd_type, is_active_queue);
491 
492 	if (pdev)
493 		psoc = wlan_pdev_get_psoc(pdev);
494 	else if (vdev)
495 		psoc = wlan_vdev_get_psoc(vdev);
496 	else if (cmd && cmd->vdev)
497 		psoc = wlan_vdev_get_psoc(cmd->vdev);
498 	else
499 		ser_debug("Can't find psoc");
500 
501 	wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock);
502 
503 	qsize = wlan_serialization_list_size(pdev_queue);
504 	while (!wlan_serialization_list_empty(pdev_queue) && qsize--) {
505 		if (wlan_serialization_get_cmd_from_queue(pdev_queue, &nnode)
506 		    != QDF_STATUS_SUCCESS) {
507 			ser_err("can't read cmd from queue");
508 			status = WLAN_SER_CMD_NOT_FOUND;
509 			break;
510 		}
511 		cmd_list =
512 			qdf_container_of(nnode,
513 					 struct wlan_serialization_command_list,
514 					 pdev_node);
515 		if (cmd && !wlan_serialization_match_cmd_id_type(
516 							nnode, cmd,
517 							WLAN_SER_PDEV_NODE)) {
518 			pnode = nnode;
519 			continue;
520 		}
521 
522 		if (vdev &&
523 		    !wlan_serialization_match_cmd_vdev(nnode,
524 						      vdev,
525 						      WLAN_SER_PDEV_NODE)) {
526 			pnode = nnode;
527 			continue;
528 		}
529 
530 		if (pdev &&
531 		    !wlan_serialization_match_cmd_pdev(nnode,
532 						       pdev,
533 						       WLAN_SER_PDEV_NODE)) {
534 			pnode = nnode;
535 			continue;
536 		}
537 
538 		/*
539 		 * active queue can't be removed directly, requester needs to
540 		 * wait for active command response and send remove request for
541 		 * active command separately
542 		 */
543 		if (is_active_queue) {
544 			if (!psoc || !cmd_list) {
545 				ser_err("psoc:0x%pK, cmd_list:0x%pK",
546 					psoc, cmd_list);
547 				status = WLAN_SER_CMD_NOT_FOUND;
548 				break;
549 			}
550 
551 			/* Cancel request received for a cmd in active
552 			 * queue which has not been activated yet, we
553 			 * should assert here
554 			 */
555 			if (qdf_atomic_test_bit(CMD_MARKED_FOR_ACTIVATION,
556 						&cmd_list->cmd_in_use)) {
557 				wlan_serialization_release_lock(
558 						&pdev_q->pdev_queue_lock);
559 				status = WLAN_SER_CMD_MARKED_FOR_ACTIVATION;
560 				goto error;
561 			}
562 
563 			qdf_status = wlan_serialization_find_and_stop_timer(
564 							psoc, &cmd_list->cmd);
565 			if (QDF_STATUS_SUCCESS != qdf_status) {
566 				ser_err("Can't fix timer for active cmd");
567 				status = WLAN_SER_CMD_NOT_FOUND;
568 				break;
569 			}
570 			status = WLAN_SER_CMD_IN_ACTIVE_LIST;
571 		}
572 
573 		qdf_mem_copy(&cmd_bkup, &cmd_list->cmd,
574 			     sizeof(struct wlan_serialization_command));
575 
576 		pdev_status =
577 			wlan_serialization_remove_node(pdev_queue,
578 						       &cmd_list->pdev_node);
579 
580 		ser_vdev_obj = wlan_serialization_get_vdev_obj(
581 					cmd_list->cmd.vdev);
582 
583 		vdev_queue = wlan_serialization_get_list_from_vdev_queue(
584 			ser_vdev_obj, cmd_type, is_active_queue);
585 
586 		vdev_status =
587 			wlan_serialization_remove_node(vdev_queue,
588 						       &cmd_list->vdev_node);
589 
590 		if (pdev_status != QDF_STATUS_SUCCESS ||
591 		    vdev_status != QDF_STATUS_SUCCESS) {
592 			ser_err("can't remove cmd from pdev/vdev queue");
593 			status = WLAN_SER_CMD_NOT_FOUND;
594 			break;
595 		}
596 
597 		qdf_mem_zero(&cmd_list->cmd,
598 			     sizeof(struct wlan_serialization_command));
599 
600 		qdf_status = wlan_serialization_insert_back(
601 			&pdev_q->cmd_pool_list,
602 			&cmd_list->pdev_node);
603 
604 		if (QDF_STATUS_SUCCESS != qdf_status) {
605 			ser_err("can't remove cmd from queue");
606 			status = WLAN_SER_CMD_NOT_FOUND;
607 			break;
608 		}
609 		nnode = pnode;
610 
611 		wlan_serialization_release_lock(&pdev_q->pdev_queue_lock);
612 		/*
613 		 * call pending cmd's callback to notify that
614 		 * it is being removed
615 		 */
616 		if (cmd_bkup.cmd_cb) {
617 			/* caller should now do necessary clean up */
618 			ser_debug("cmd cb: type[%d] id[%d]",
619 				  cmd_bkup.cmd_type,
620 				  cmd_bkup.cmd_id);
621 			ser_debug("reason: WLAN_SER_CB_CANCEL_CMD");
622 			cmd_bkup.cmd_cb(&cmd_bkup,
623 					WLAN_SER_CB_CANCEL_CMD);
624 			/* caller should release the memory */
625 			ser_debug("reason: WLAN_SER_CB_RELEASE_MEM_CMD");
626 			cmd_bkup.cmd_cb(&cmd_bkup,
627 					WLAN_SER_CB_RELEASE_MEM_CMD);
628 		}
629 
630 		wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock);
631 
632 		if (is_active_queue) {
633 			if (cmd_bkup.is_blocking)
634 				pdev_q->blocking_cmd_active = 0;
635 			pdev_q->vdev_active_cmd_bitmap &=
636 				 ~(1 << wlan_vdev_get_id(cmd_bkup.vdev));
637 		} else {
638 			if (cmd_bkup.is_blocking)
639 				pdev_q->blocking_cmd_waiting--;
640 
641 			status = WLAN_SER_CMD_IN_PENDING_LIST;
642 		}
643 
644 
645 		if (!vdev && !pdev)
646 			break;
647 	}
648 
649 	wlan_serialization_release_lock(&pdev_q->pdev_queue_lock);
650 
651 error:
652 	ser_exit();
653 	return status;
654 }
655