xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_internal.c (revision 27d564647e9b50e713c60b0d7e5ea2a9b0a3ae74)
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_internal.c
20  * This file defines the functions which are called
21  * from serialization public API's and are internal
22  * to serialization.
23  */
24 
25 #include <wlan_objmgr_vdev_obj.h>
26 #include <wlan_objmgr_pdev_obj.h>
27 #include <wlan_objmgr_psoc_obj.h>
28 #include <qdf_list.h>
29 #include <qdf_status.h>
30 #include <wlan_utility.h>
31 #include "wlan_serialization_api.h"
32 #include "wlan_serialization_main_i.h"
33 #include "wlan_serialization_utils_i.h"
34 #include "wlan_serialization_non_scan_i.h"
35 #include "wlan_serialization_scan_i.h"
36 #include "wlan_serialization_internal_i.h"
37 
38 bool wlan_serialization_is_cmd_present_queue(
39 			struct wlan_serialization_command *cmd,
40 			uint8_t is_active_queue)
41 {
42 	qdf_list_t *queue;
43 	bool status = false;
44 	enum wlan_serialization_node node_type;
45 	struct wlan_ser_pdev_obj *ser_pdev_obj;
46 	struct wlan_ser_vdev_obj *ser_vdev_obj;
47 	enum wlan_serialization_cmd_type cmd_type;
48 
49 	if (!cmd) {
50 		ser_err("invalid cmd");
51 		goto error;
52 	}
53 
54 	cmd_type = cmd->cmd_type;
55 
56 	ser_pdev_obj = wlan_serialization_get_pdev_obj(
57 			wlan_serialization_get_pdev_from_cmd(cmd));
58 
59 	if (!ser_pdev_obj) {
60 		ser_err("invalid ser vdev obj");
61 		goto error;
62 	}
63 
64 	ser_vdev_obj = wlan_serialization_get_vdev_obj(
65 			wlan_serialization_get_vdev_from_cmd(cmd));
66 	if (!ser_vdev_obj) {
67 		ser_err("invalid ser pdev obj");
68 		goto error;
69 	}
70 
71 	if (cmd_type < WLAN_SER_CMD_NONSCAN) {
72 		queue = wlan_serialization_get_list_from_pdev_queue(
73 				ser_pdev_obj, cmd_type, is_active_queue);
74 		node_type = WLAN_SER_PDEV_NODE;
75 	} else {
76 		queue = wlan_serialization_get_list_from_vdev_queue(
77 				ser_vdev_obj, cmd_type, is_active_queue);
78 		node_type = WLAN_SER_VDEV_NODE;
79 	}
80 
81 	status = wlan_serialization_is_cmd_present_in_given_queue(queue, cmd,
82 								  node_type);
83 
84 error:
85 	return status;
86 }
87 
88 enum wlan_serialization_status
89 wlan_serialization_enqueue_cmd(struct wlan_serialization_command *cmd)
90 {
91 	enum wlan_serialization_status status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
92 	struct wlan_serialization_command_list *cmd_list;
93 	qdf_list_node_t *nnode;
94 	struct wlan_objmgr_pdev *pdev;
95 	struct wlan_ser_pdev_obj *ser_pdev_obj;
96 	struct wlan_serialization_pdev_queue *pdev_queue;
97 	bool active_queue;
98 
99 	/* Enqueue process
100 	 * 1) peek through command structure and see what is the command type
101 	 * 2) two main types of commands to process
102 	 *    a) SCAN
103 	 *    b) NON-SCAN
104 	 * 3) for each command there are separate command queues per pdev
105 	 * 4) pull pdev from vdev structure and get the command queue associated
106 	 *    with that pdev and try to enqueue on those queue
107 	 * 5) Thumb rule:
108 	 *    a) There could be only 1 active non-scan command at a
109 	 *       time including all total non-scan commands of all pdevs.
110 	 *
111 	 *       example: pdev1 has 1 non-scan active command and
112 	 *       pdev2 got 1 non-scan command then that command should go to
113 	 *       pdev2's pending queue
114 	 *
115 	 *    b) There could be only N number of scan commands at a time
116 	 *       including all total scan commands of all pdevs
117 	 *
118 	 *       example: Let's say N=8,
119 	 *       pdev1's vdev1 has 5 scan command, pdev2's vdev1 has 3
120 	 *       scan commands, if we get scan request on vdev2 then it will go
121 	 *       to pending queue of vdev2 as we reached max allowed scan active
122 	 *       command.
123 	 */
124 
125 	ser_enter();
126 
127 	if (!cmd) {
128 		ser_err("NULL command");
129 		goto error;
130 	}
131 
132 	if (!cmd->cmd_cb) {
133 		ser_err("no cmd_cb for cmd type:%d, id: %d",
134 			cmd->cmd_type,
135 			cmd->cmd_id);
136 		goto error;
137 	}
138 
139 	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
140 	if (!pdev) {
141 		ser_err("pdev is invalid");
142 		goto error;
143 	}
144 
145 	ser_pdev_obj =
146 		wlan_objmgr_pdev_get_comp_private_obj(
147 				pdev,
148 				WLAN_UMAC_COMP_SERIALIZATION);
149 	if (!ser_pdev_obj) {
150 		ser_err("Invalid ser_pdev_obj");
151 		goto error;
152 	}
153 
154 	pdev_queue = wlan_serialization_get_pdev_queue_obj(ser_pdev_obj,
155 							   cmd->cmd_type);
156 	if (!pdev_queue) {
157 		ser_err("pdev_queue is invalid");
158 		goto error;
159 	}
160 
161 	ser_debug("enqueue cmd: type[%d] id[%d] high_priority[%d] blocking[%d]",
162 		  cmd->cmd_type,
163 		  cmd->cmd_id,
164 		  cmd->is_high_priority,
165 		  cmd->is_blocking);
166 
167 	wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock);
168 
169 	active_queue = wlan_serialization_is_active_cmd_allowed(cmd);
170 
171 	if (wlan_serialization_is_cmd_present_queue(cmd, active_queue)) {
172 		wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
173 		ser_err("duplicate command, can't enqueue");
174 		goto error;
175 	}
176 
177 	if (wlan_serialization_remove_front(
178 				&pdev_queue->cmd_pool_list,
179 				&nnode) != QDF_STATUS_SUCCESS) {
180 		wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
181 		ser_err("Failed to get cmd buffer from global pool");
182 		status = WLAN_SER_CMD_DENIED_LIST_FULL;
183 		goto error;
184 	}
185 
186 	ser_debug("Global pool node: %pK", nnode);
187 
188 	cmd_list =
189 		qdf_container_of(nnode,
190 				 struct wlan_serialization_command_list,
191 				 pdev_node);
192 
193 	qdf_mem_copy(&cmd_list->cmd, cmd,
194 		     sizeof(struct wlan_serialization_command));
195 
196 	if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN) {
197 		status = wlan_ser_add_scan_cmd(ser_pdev_obj,
198 					       cmd_list,
199 					       active_queue);
200 	} else {
201 		status = wlan_ser_add_non_scan_cmd(ser_pdev_obj,
202 						   cmd_list,
203 						   active_queue);
204 	}
205 
206 	if (status != WLAN_SER_CMD_PENDING && status != WLAN_SER_CMD_ACTIVE) {
207 		ser_err("Failed to add cmd to active/pending queue");
208 		qdf_mem_zero(&cmd_list->cmd,
209 			     sizeof(struct wlan_serialization_command));
210 		wlan_serialization_insert_back(
211 			&pdev_queue->cmd_pool_list,
212 			&cmd_list->pdev_node);
213 	}
214 
215 	if (WLAN_SER_CMD_ACTIVE == status) {
216 		qdf_atomic_set_bit(CMD_MARKED_FOR_ACTIVATION,
217 				   &cmd_list->cmd_in_use);
218 	}
219 
220 	wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
221 
222 	if (WLAN_SER_CMD_ACTIVE == status)
223 		wlan_serialization_activate_cmd(cmd_list,
224 						ser_pdev_obj);
225 
226 error:
227 	ser_exit();
228 
229 	return status;
230 }
231 
232 QDF_STATUS wlan_serialization_activate_cmd(
233 			struct wlan_serialization_command_list *cmd_list,
234 			struct wlan_ser_pdev_obj *ser_pdev_obj)
235 {
236 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
237 	struct wlan_objmgr_psoc *psoc = NULL;
238 	struct wlan_serialization_pdev_queue *pdev_queue;
239 
240 	pdev_queue = wlan_serialization_get_pdev_queue_obj(
241 			ser_pdev_obj, cmd_list->cmd.cmd_type);
242 
243 	psoc = wlan_vdev_get_psoc(cmd_list->cmd.vdev);
244 	if (!psoc) {
245 		ser_err("invalid psoc");
246 		goto error;
247 	}
248 
249 	/*
250 	 * command is already pushed to active queue above
251 	 * now start the timer and notify requestor
252 	 */
253 	wlan_serialization_find_and_start_timer(psoc, &cmd_list->cmd);
254 	/*
255 	 * Remember that serialization module may send
256 	 * this callback in same context through which it
257 	 * received the serialization request. Due to which
258 	 * it is caller's responsibility to ensure acquiring
259 	 * and releasing its own lock appropriately.
260 	 */
261 
262 	ser_debug("cmd cb: type[%d] id[%d] : reason: %s",
263 		  cmd_list->cmd.cmd_type,
264 		  cmd_list->cmd.cmd_id,
265 		  "WLAN_SER_CB_ACTIVATE_CMD");
266 
267 	status = cmd_list->cmd.cmd_cb(&cmd_list->cmd,
268 				WLAN_SER_CB_ACTIVATE_CMD);
269 
270 	wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock);
271 
272 	qdf_atomic_clear_bit(CMD_MARKED_FOR_ACTIVATION,
273 			     &cmd_list->cmd_in_use);
274 	qdf_atomic_set_bit(CMD_IS_ACTIVE,
275 			   &cmd_list->cmd_in_use);
276 
277 	wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
278 
279 	if (QDF_IS_STATUS_ERROR(status))
280 		wlan_serialization_dequeue_cmd(&cmd_list->cmd, true);
281 
282 error:
283 	return status;
284 }
285 
286 bool
287 wlan_serialization_is_active_cmd_allowed(struct wlan_serialization_command *cmd)
288 {
289 	struct wlan_objmgr_pdev *pdev;
290 	bool active_cmd_allowed = 0;
291 
292 	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
293 	if (!pdev) {
294 		ser_err("NULL pdev");
295 		goto error;
296 	}
297 
298 	if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN)
299 		active_cmd_allowed =
300 			wlan_serialization_is_active_scan_cmd_allowed(cmd);
301 	else
302 		active_cmd_allowed =
303 			wlan_serialization_is_active_non_scan_cmd_allowed(cmd);
304 
305 	ser_debug("active cmd_type[%d] cmd_id[%d] allowed: %d",
306 		  cmd->cmd_type,
307 		  cmd->cmd_id,
308 		  active_cmd_allowed);
309 
310 error:
311 	return active_cmd_allowed;
312 }
313 
314 enum wlan_serialization_status
315 wlan_serialization_move_pending_to_active(
316 		enum wlan_serialization_cmd_type cmd_type,
317 		struct wlan_ser_pdev_obj *ser_pdev_obj,
318 		struct wlan_objmgr_vdev *vdev,
319 		bool blocking_cmd_removed)
320 {
321 	enum wlan_serialization_status status;
322 
323 	if (cmd_type < WLAN_SER_CMD_NONSCAN) {
324 		status =
325 		wlan_ser_move_scan_pending_to_active(
326 				ser_pdev_obj);
327 	} else {
328 		status =
329 		wlan_ser_move_non_scan_pending_to_active(
330 				ser_pdev_obj,
331 				vdev,
332 				blocking_cmd_removed);
333 	}
334 
335 	return status;
336 }
337 
338 enum wlan_serialization_cmd_status
339 wlan_serialization_dequeue_cmd(struct wlan_serialization_command *cmd,
340 			       uint8_t active_cmd)
341 {
342 	enum wlan_serialization_cmd_status status =
343 		WLAN_SER_CMD_NOT_FOUND;
344 	enum wlan_serialization_status ser_status =
345 		WLAN_SER_CMD_DENIED_UNSPECIFIED;
346 
347 	QDF_STATUS qdf_status;
348 	struct wlan_objmgr_pdev *pdev;
349 	struct wlan_objmgr_psoc *psoc;
350 	struct wlan_ser_pdev_obj *ser_pdev_obj;
351 	struct wlan_serialization_command cmd_bkup;
352 	struct wlan_serialization_command_list *cmd_list;
353 	struct wlan_serialization_pdev_queue *pdev_queue;
354 	bool blocking_cmd_removed = 0;
355 
356 	ser_enter();
357 
358 	if (!cmd) {
359 		ser_err("NULL command");
360 		goto error;
361 	}
362 
363 	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
364 	if (!pdev) {
365 		ser_err("invalid pdev");
366 		goto error;
367 	}
368 
369 	psoc = wlan_pdev_get_psoc(pdev);
370 	if (!psoc) {
371 		ser_err("invalid psoc");
372 		goto error;
373 	}
374 
375 	ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev);
376 	if (!ser_pdev_obj) {
377 		ser_err("ser_pdev_obj is empty");
378 		goto error;
379 	}
380 
381 	pdev_queue = wlan_serialization_get_pdev_queue_obj(
382 			ser_pdev_obj, cmd->cmd_type);
383 
384 	ser_debug("dequeue cmd: type[%d] id[%d] high_priority[%d] blocking[%d]",
385 		  cmd->cmd_type,
386 		  cmd->cmd_id,
387 		  cmd->is_high_priority,
388 		  cmd->is_blocking);
389 
390 	wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock);
391 
392 	if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN)
393 		qdf_status = wlan_ser_remove_scan_cmd(
394 				ser_pdev_obj, &cmd_list, cmd, active_cmd);
395 	else {
396 		qdf_status = wlan_ser_remove_non_scan_cmd(
397 				ser_pdev_obj, &cmd_list, cmd, active_cmd);
398 	}
399 
400 	if (qdf_status != QDF_STATUS_SUCCESS) {
401 		wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
402 		status = WLAN_SER_CMD_NOT_FOUND;
403 		goto error;
404 	}
405 
406 	if (active_cmd) {
407 		if (cmd_list->cmd.cmd_type >= WLAN_SER_CMD_NONSCAN)
408 			blocking_cmd_removed = cmd_list->cmd.is_blocking;
409 	}
410 
411 	if (active_cmd)
412 		wlan_serialization_find_and_stop_timer(psoc, &cmd_list->cmd);
413 
414 	qdf_mem_copy(&cmd_bkup, &cmd_list->cmd,
415 		     sizeof(struct wlan_serialization_command));
416 	qdf_mem_zero(&cmd_list->cmd,
417 		     sizeof(struct wlan_serialization_command));
418 	qdf_status = wlan_serialization_insert_back(
419 			&pdev_queue->cmd_pool_list,
420 			&cmd_list->pdev_node);
421 
422 	wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
423 
424 	/* Call cmd cb for remove request*/
425 	if (cmd_bkup.cmd_cb) {
426 		/* caller should release the memory */
427 		ser_debug("cmd cb: type[%d] id[%d]: reason: %s",
428 			  cmd_bkup.cmd_type,
429 			  cmd_bkup.cmd_id,
430 			  "WLAN_SER_CB_RELEASE_MEM_CMD");
431 		cmd_bkup.cmd_cb(&cmd_bkup,
432 				     WLAN_SER_CB_RELEASE_MEM_CMD);
433 	}
434 
435 	if (active_cmd) {
436 		ser_status = wlan_serialization_move_pending_to_active(
437 			cmd_bkup.cmd_type, ser_pdev_obj,
438 			cmd_bkup.vdev,
439 			blocking_cmd_removed);
440 	}
441 
442 	if (active_cmd)
443 		status = WLAN_SER_CMD_IN_ACTIVE_LIST;
444 	else
445 		status = WLAN_SER_CMD_IN_PENDING_LIST;
446 
447 error:
448 	ser_exit();
449 	return status;
450 }
451 
452 void wlan_serialization_generic_timer_cb(void *arg)
453 {
454 	struct wlan_serialization_timer *timer = arg;
455 	struct wlan_serialization_command *cmd = timer->cmd;
456 
457 	if (!cmd) {
458 		ser_err("command not found");
459 		QDF_ASSERT(0);
460 		return;
461 	}
462 
463 	ser_err("active cmd timeout for cmd_type[%d] vdev[%pK]",
464 		cmd->cmd_type, cmd->vdev);
465 
466 	if (cmd->cmd_cb)
467 		cmd->cmd_cb(cmd, WLAN_SER_CB_ACTIVE_CMD_TIMEOUT);
468 
469 	/*
470 	 * dequeue cmd API will cleanup and destroy the timer. If it fails to
471 	 * dequeue command then we have to destroy the timer.
472 	 */
473 	wlan_serialization_dequeue_cmd(cmd, true);
474 }
475 
476 static QDF_STATUS wlan_serialization_mc_flush_noop(struct scheduler_msg *msg)
477 {
478 	return QDF_STATUS_SUCCESS;
479 }
480 
481 static void
482 wlan_serialization_timer_cb_mc_ctx(void *arg)
483 {
484 	struct scheduler_msg msg = {0};
485 
486 	msg.type = SYS_MSG_ID_MC_TIMER;
487 	msg.reserved = SYS_MSG_COOKIE;
488 	msg.callback = wlan_serialization_generic_timer_cb;
489 	msg.bodyptr = arg;
490 	msg.bodyval = 0;
491 	msg.flush_callback = wlan_serialization_mc_flush_noop;
492 
493 	if (scheduler_post_msg(QDF_MODULE_ID_SYS, &msg) == QDF_STATUS_SUCCESS)
494 		return;
495 
496 	ser_err("Could not enqueue timer to timer queue");
497 }
498 
499 #ifdef CONFIG_MCL
500 static void wlan_serialization_timer_handler(void *arg)
501 {
502 	ser_enter();
503 
504 	wlan_serialization_timer_cb_mc_ctx(arg);
505 
506 	ser_exit();
507 }
508 #else
509 static void wlan_serialization_timer_handler(void *arg)
510 {
511 	struct wlan_serialization_timer *timer = arg;
512 	struct wlan_serialization_command *cmd = timer->cmd;
513 
514 	if (!cmd) {
515 		ser_err("command not found");
516 		QDF_ASSERT(0);
517 		return;
518 	}
519 
520 	if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN)
521 		wlan_serialization_timer_cb_mc_ctx(arg);
522 	else
523 		wlan_serialization_generic_timer_cb(arg);
524 }
525 #endif
526 
527 QDF_STATUS
528 wlan_serialization_find_and_stop_timer(struct wlan_objmgr_psoc *psoc,
529 				       struct wlan_serialization_command *cmd)
530 {
531 	struct wlan_ser_psoc_obj *psoc_ser_obj;
532 	struct wlan_serialization_timer *ser_timer;
533 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
534 	int i = 0;
535 	uint32_t phy_version;
536 
537 	if (!psoc || !cmd) {
538 		ser_err("invalid param");
539 		goto exit;
540 	}
541 
542 	if (cmd->cmd_timeout_duration == 0) {
543 		phy_version = wlan_psoc_get_nif_phy_version(psoc);
544 		if (wlan_is_emulation_platform(phy_version)) {
545 			ser_err("[SCAN-EMULATION]: Not performing timer funcs");
546 			status = QDF_STATUS_SUCCESS;
547 		goto exit;
548 		}
549 	}
550 
551 	psoc_ser_obj = wlan_serialization_get_psoc_obj(psoc);
552 	/*
553 	 * Here cmd_id and cmd_type are used to locate the timer being
554 	 * associated with command.
555 	 */
556 	wlan_serialization_acquire_lock(&psoc_ser_obj->timer_lock);
557 
558 	for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) {
559 		ser_timer = &psoc_ser_obj->timers[i];
560 		if (!(ser_timer->cmd) ||
561 		    (ser_timer->cmd->cmd_id != cmd->cmd_id) ||
562 		    (ser_timer->cmd->cmd_type != cmd->cmd_type) ||
563 		    (ser_timer->cmd->vdev != cmd->vdev))
564 			continue;
565 
566 		status = QDF_STATUS_SUCCESS;
567 		break;
568 	}
569 
570 	wlan_serialization_release_lock(&psoc_ser_obj->timer_lock);
571 
572 	if (QDF_IS_STATUS_SUCCESS(status)) {
573 		status = wlan_serialization_stop_timer(ser_timer);
574 		ser_debug("\n Stopping timer for cmd type:%d, id: %d",
575 			  cmd->cmd_type, cmd->cmd_id);
576 	} else {
577 		ser_err("Can't find timer for cmd_type[%d]", cmd->cmd_type);
578 	}
579 
580 exit:
581 	return status;
582 }
583 
584 QDF_STATUS
585 wlan_serialization_find_and_start_timer(struct wlan_objmgr_psoc *psoc,
586 					struct wlan_serialization_command *cmd)
587 {
588 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
589 	struct wlan_ser_psoc_obj *psoc_ser_obj;
590 	struct wlan_serialization_timer *ser_timer;
591 	int i = 0;
592 	uint32_t nif_phy_ver;
593 
594 	if (!psoc || !cmd) {
595 		ser_err("invalid param");
596 		goto error;
597 	}
598 
599 	nif_phy_ver = wlan_psoc_get_nif_phy_version(psoc);
600 	if ((cmd->cmd_timeout_duration == 0) &&
601 	    (wlan_is_emulation_platform(nif_phy_ver))) {
602 		ser_err("[SCAN-EMULATION]: Not performing timer functions\n");
603 		status = QDF_STATUS_SUCCESS;
604 		goto exit;
605 	}
606 
607 	psoc_ser_obj = wlan_serialization_get_psoc_obj(psoc);
608 
609 	wlan_serialization_acquire_lock(&psoc_ser_obj->timer_lock);
610 
611 	for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) {
612 		/* Keep trying timer */
613 		ser_timer = &psoc_ser_obj->timers[i];
614 		if (ser_timer->cmd)
615 			continue;
616 
617 		/* Remember timer is pointing to command */
618 		ser_timer->cmd = cmd;
619 		status = QDF_STATUS_SUCCESS;
620 		break;
621 	}
622 
623 	wlan_serialization_release_lock(&psoc_ser_obj->timer_lock);
624 
625 	if (QDF_IS_STATUS_SUCCESS(status)) {
626 		qdf_timer_init(NULL,
627 			       &ser_timer->timer,
628 			       wlan_serialization_timer_handler,
629 			       ser_timer,
630 			       QDF_TIMER_TYPE_SW);
631 			       qdf_timer_mod(&ser_timer->timer,
632 			       cmd->cmd_timeout_duration);
633 
634 		ser_debug("starting timer for cmd: type[%d] id[%d] high_priority[%d] blocking[%d]",
635 			  cmd->cmd_type,
636 			  cmd->cmd_id,
637 			  cmd->is_high_priority,
638 			  cmd->is_blocking);
639 	}
640 
641 error:
642 exit:
643 
644 	return status;
645 }
646 
647 enum wlan_serialization_cmd_status
648 wlan_serialization_cmd_cancel_handler(
649 		struct wlan_ser_pdev_obj *ser_obj,
650 		struct wlan_serialization_command *cmd,
651 		struct wlan_objmgr_pdev *pdev, struct wlan_objmgr_vdev *vdev,
652 		enum wlan_serialization_cmd_type cmd_type, uint8_t queue_type)
653 {
654 	enum wlan_serialization_cmd_status active_status =
655 		WLAN_SER_CMD_NOT_FOUND;
656 	enum wlan_serialization_cmd_status pending_status =
657 		WLAN_SER_CMD_NOT_FOUND;
658 	enum wlan_serialization_cmd_status status =
659 		WLAN_SER_CMD_NOT_FOUND;
660 
661 	ser_enter();
662 
663 	if (!ser_obj) {
664 		ser_err("invalid serial object");
665 		goto error;
666 	}
667 
668 	if (queue_type & WLAN_SERIALIZATION_ACTIVE_QUEUE) {
669 		if (cmd_type < WLAN_SER_CMD_NONSCAN)
670 			active_status = wlan_ser_cancel_scan_cmd(
671 					ser_obj, pdev, vdev, cmd,
672 					cmd_type, true);
673 		else
674 			active_status = wlan_ser_cancel_non_scan_cmd(
675 					ser_obj, pdev, vdev, cmd,
676 					cmd_type, true);
677 	}
678 
679 	if (queue_type & WLAN_SERIALIZATION_PENDING_QUEUE) {
680 		if (cmd_type < WLAN_SER_CMD_NONSCAN)
681 			pending_status = wlan_ser_cancel_scan_cmd(
682 					ser_obj, pdev, vdev, cmd,
683 					cmd_type, false);
684 		else
685 			pending_status = wlan_ser_cancel_non_scan_cmd(
686 					ser_obj, pdev, vdev, cmd,
687 					cmd_type, false);
688 	}
689 
690 	if (active_status == WLAN_SER_CMD_IN_ACTIVE_LIST &&
691 	    pending_status == WLAN_SER_CMD_IN_PENDING_LIST)
692 		status = WLAN_SER_CMDS_IN_ALL_LISTS;
693 	else if (active_status == WLAN_SER_CMD_IN_ACTIVE_LIST)
694 		status = active_status;
695 	else if (pending_status == WLAN_SER_CMD_IN_PENDING_LIST)
696 		status = pending_status;
697 
698 error:
699 	ser_exit();
700 	return status;
701 }
702 
703 enum wlan_serialization_cmd_status
704 wlan_serialization_find_and_cancel_cmd(
705 		struct wlan_serialization_command *cmd,
706 		enum wlan_serialization_cancel_type req_type,
707 		uint8_t queue_type)
708 {
709 	enum wlan_serialization_cmd_status status = WLAN_SER_CMD_NOT_FOUND;
710 	struct wlan_ser_pdev_obj *ser_obj = NULL;
711 	struct wlan_objmgr_pdev *pdev;
712 
713 	ser_enter();
714 
715 	if (!cmd) {
716 		ser_err("Invalid cmd");
717 		goto error;
718 	}
719 
720 	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
721 	if (!pdev) {
722 		ser_err("Invalid pdev");
723 		goto error;
724 	}
725 	ser_obj = wlan_serialization_get_pdev_obj(pdev);
726 	if (!ser_obj) {
727 		ser_err("Invalid ser_obj");
728 		goto error;
729 	}
730 
731 	switch (req_type) {
732 	case WLAN_SER_CANCEL_SINGLE_SCAN:
733 		/* remove scan cmd which matches the given cmd struct */
734 		status =  wlan_serialization_cmd_cancel_handler(ser_obj,
735 								cmd,
736 								NULL,
737 								NULL,
738 								cmd->cmd_type,
739 								queue_type);
740 		break;
741 	case WLAN_SER_CANCEL_PDEV_SCANS:
742 		/* remove all scan cmds which matches the pdev object */
743 		status = wlan_serialization_cmd_cancel_handler(
744 				ser_obj,
745 				NULL,
746 				wlan_vdev_get_pdev(cmd->vdev),
747 				NULL,
748 				cmd->cmd_type,
749 				queue_type);
750 		break;
751 	case WLAN_SER_CANCEL_VDEV_SCANS:
752 		/* remove all scan cmds which matches the vdev object */
753 		status = wlan_serialization_cmd_cancel_handler(ser_obj,
754 							       NULL, NULL,
755 							       cmd->vdev,
756 							       cmd->cmd_type,
757 							       queue_type);
758 		break;
759 	case WLAN_SER_CANCEL_NON_SCAN_CMD:
760 		/* remove nonscan cmd which matches the given cmd */
761 		status = wlan_serialization_cmd_cancel_handler(ser_obj,
762 							       cmd,
763 							       NULL,
764 							       NULL,
765 							       cmd->cmd_type,
766 							       queue_type);
767 		break;
768 	case WLAN_SER_CANCEL_PDEV_NON_SCAN_CMD:
769 		/* remove all non scan cmds which matches the pdev object */
770 		status = wlan_serialization_cmd_cancel_handler(
771 				ser_obj,
772 				NULL,
773 				wlan_vdev_get_pdev(cmd->vdev),
774 				NULL,
775 				cmd->cmd_type,
776 				queue_type);
777 		break;
778 	case WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD:
779 		/* remove all non scan cmds which matches the vdev object */
780 		status = wlan_serialization_cmd_cancel_handler(ser_obj,
781 							       NULL, NULL,
782 							       cmd->vdev,
783 							       cmd->cmd_type,
784 							       queue_type);
785 		break;
786 	default:
787 		ser_err("Invalid request");
788 	}
789 
790 error:
791 	ser_exit();
792 	return status;
793 }
794