xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_internal.c (revision 1397a33f48ea6455be40871470b286e535820eb8)
1 /*
2  * Copyright (c) 2017-2019 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 			       enum ser_queue_reason ser_reason)
91 {
92 	enum wlan_serialization_status status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
93 	struct wlan_serialization_command_list *cmd_list;
94 	qdf_list_node_t *nnode;
95 	struct wlan_objmgr_pdev *pdev;
96 	struct wlan_ser_pdev_obj *ser_pdev_obj;
97 	struct wlan_serialization_pdev_queue *pdev_queue;
98 	struct wlan_ser_vdev_obj *ser_vdev_obj;
99 	struct wlan_serialization_vdev_queue *vdev_queue;
100 	bool active_queue;
101 
102 	/* Enqueue process
103 	 * 1) peek through command structure and see what is the command type
104 	 * 2) two main types of commands to process
105 	 *    a) SCAN
106 	 *    b) NON-SCAN
107 	 * 3) for each command there are separate command queues per pdev
108 	 * 4) pull pdev from vdev structure and get the command queue associated
109 	 *    with that pdev and try to enqueue on those queue
110 	 * 5) Thumb rule:
111 	 *    a) There could be only 1 active non-scan command at a
112 	 *       time including all total non-scan commands of all pdevs.
113 	 *
114 	 *       example: pdev1 has 1 non-scan active command and
115 	 *       pdev2 got 1 non-scan command then that command should go to
116 	 *       pdev2's pending queue
117 	 *
118 	 *    b) There could be only N number of scan commands at a time
119 	 *       including all total scan commands of all pdevs
120 	 *
121 	 *       example: Let's say N=8,
122 	 *       pdev1's vdev1 has 5 scan command, pdev2's vdev1 has 3
123 	 *       scan commands, if we get scan request on vdev2 then it will go
124 	 *       to pending queue of vdev2 as we reached max allowed scan active
125 	 *       command.
126 	 */
127 
128 	ser_enter();
129 
130 	if (!cmd) {
131 		ser_err("NULL command");
132 		goto error;
133 	}
134 
135 	if (!cmd->cmd_cb) {
136 		ser_err("no cmd_cb for cmd type:%d, id: %d",
137 			cmd->cmd_type,
138 			cmd->cmd_id);
139 		goto error;
140 	}
141 
142 	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
143 	if (!pdev) {
144 		ser_err("pdev is invalid");
145 		goto error;
146 	}
147 
148 	ser_pdev_obj =
149 		wlan_objmgr_pdev_get_comp_private_obj(
150 				pdev,
151 				WLAN_UMAC_COMP_SERIALIZATION);
152 	if (!ser_pdev_obj) {
153 		ser_err("Invalid ser_pdev_obj");
154 		goto error;
155 	}
156 
157 	pdev_queue = wlan_serialization_get_pdev_queue_obj(ser_pdev_obj,
158 							   cmd->cmd_type);
159 	if (!pdev_queue) {
160 		ser_err("pdev_queue is invalid");
161 		goto error;
162 	}
163 
164 	ser_debug("enqueue cmd: type[%d] id[%d] high_priority[%d] blocking[%d]",
165 		  cmd->cmd_type,
166 		  cmd->cmd_id,
167 		  cmd->is_high_priority,
168 		  cmd->is_blocking);
169 
170 	wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock);
171 
172 	/* Before queuing any non scan command,
173 	 * as part of wlan_serialization_request,
174 	 * we check if the vdev queues are disabled.
175 	 *
176 	 * The serialization command structure has an
177 	 * attribute, where after a given command is queued,
178 	 * we can block the vdev queues.
179 	 *
180 	 * For example, after VDEV_DOWN command is queued as
181 	 * part of a vdev deletion, no other commands should be queued
182 	 * until the deletion is complete, so with VDEV_DOWN(in case of
183 	 * vdev deletion) with pass the attribute to disable vdev queues
184 	 */
185 	if (cmd->cmd_type > WLAN_SER_CMD_SCAN &&
186 	    ser_reason == SER_REQUEST) {
187 		ser_vdev_obj =
188 			wlan_serialization_get_vdev_obj(
189 				wlan_serialization_get_vdev_from_cmd(cmd));
190 
191 		if (!ser_vdev_obj) {
192 			wlan_serialization_release_lock(
193 				&pdev_queue->pdev_queue_lock);
194 			goto error;
195 		}
196 
197 		vdev_queue =
198 			wlan_serialization_get_vdev_queue_obj(
199 				ser_vdev_obj,
200 				cmd->cmd_type);
201 
202 		if (!vdev_queue) {
203 			wlan_serialization_release_lock(
204 				&pdev_queue->pdev_queue_lock);
205 			goto error;
206 		}
207 
208 		if (vdev_queue->queue_disable) {
209 			wlan_serialization_release_lock(
210 				&pdev_queue->pdev_queue_lock);
211 			ser_err("VDEV queue is disabled, ser request denied");
212 			ser_err("cmd id[%d] cmd type[%d]", cmd->cmd_id,
213 				cmd->cmd_type);
214 			status = WLAN_SER_CMD_QUEUE_DISABLED;
215 			goto error;
216 		}
217 	}
218 
219 	active_queue = wlan_serialization_is_active_cmd_allowed(cmd);
220 
221 	if (wlan_serialization_is_cmd_present_queue(cmd, active_queue)) {
222 		wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
223 		ser_err("duplicate command, can't enqueue");
224 		goto error;
225 	}
226 
227 	if (wlan_serialization_remove_front(
228 				&pdev_queue->cmd_pool_list,
229 				&nnode) != QDF_STATUS_SUCCESS) {
230 		wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
231 		ser_err("Failed to get cmd buffer from global pool");
232 		status = WLAN_SER_CMD_DENIED_LIST_FULL;
233 		goto error;
234 	}
235 
236 	ser_debug("Global pool node: %pK", nnode);
237 
238 	cmd_list =
239 		qdf_container_of(nnode,
240 				 struct wlan_serialization_command_list,
241 				 pdev_node);
242 
243 	qdf_mem_copy(&cmd_list->cmd, cmd,
244 		     sizeof(struct wlan_serialization_command));
245 
246 	if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN) {
247 		status = wlan_ser_add_scan_cmd(ser_pdev_obj,
248 					       cmd_list,
249 					       active_queue);
250 	} else {
251 		status = wlan_ser_add_non_scan_cmd(ser_pdev_obj,
252 						   cmd_list,
253 						   active_queue);
254 	}
255 
256 	if (status != WLAN_SER_CMD_PENDING && status != WLAN_SER_CMD_ACTIVE) {
257 		qdf_mem_zero(&cmd_list->cmd,
258 			     sizeof(struct wlan_serialization_command));
259 		wlan_serialization_insert_back(
260 			&pdev_queue->cmd_pool_list,
261 			&cmd_list->pdev_node);
262 		wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
263 		ser_err("Failed to add cmd to active/pending queue");
264 		goto error;
265 	}
266 
267 	if (WLAN_SER_CMD_ACTIVE == status) {
268 		qdf_atomic_set_bit(CMD_MARKED_FOR_ACTIVATION,
269 				   &cmd_list->cmd_in_use);
270 	}
271 
272 	wlan_ser_update_cmd_history(pdev_queue, &cmd_list->cmd,
273 				    ser_reason, true, active_queue);
274 
275 	wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
276 
277 	if (WLAN_SER_CMD_ACTIVE == status)
278 		wlan_serialization_activate_cmd(cmd_list,
279 						ser_pdev_obj, ser_reason);
280 
281 error:
282 	ser_exit();
283 
284 	return status;
285 }
286 
287 QDF_STATUS wlan_serialization_activate_cmd(
288 			struct wlan_serialization_command_list *cmd_list,
289 			struct wlan_ser_pdev_obj *ser_pdev_obj,
290 			enum ser_queue_reason ser_reason)
291 {
292 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
293 	struct wlan_objmgr_psoc *psoc = NULL;
294 	struct wlan_serialization_pdev_queue *pdev_queue;
295 
296 	pdev_queue = wlan_serialization_get_pdev_queue_obj(
297 			ser_pdev_obj, cmd_list->cmd.cmd_type);
298 
299 	psoc = wlan_vdev_get_psoc(cmd_list->cmd.vdev);
300 	if (!psoc) {
301 		ser_err("invalid psoc");
302 		goto error;
303 	}
304 
305 	/*
306 	 * command is already pushed to active queue above
307 	 * now start the timer and notify requestor
308 	 */
309 	wlan_serialization_find_and_start_timer(psoc, &cmd_list->cmd);
310 	/*
311 	 * Remember that serialization module may send
312 	 * this callback in same context through which it
313 	 * received the serialization request. Due to which
314 	 * it is caller's responsibility to ensure acquiring
315 	 * and releasing its own lock appropriately.
316 	 */
317 
318 	ser_debug("cmd cb: type[%d] id[%d] : reason: %s",
319 		  cmd_list->cmd.cmd_type,
320 		  cmd_list->cmd.cmd_id,
321 		  "WLAN_SER_CB_ACTIVATE_CMD");
322 
323 	cmd_list->cmd.activation_reason = ser_reason;
324 
325 	status = cmd_list->cmd.cmd_cb(&cmd_list->cmd,
326 				WLAN_SER_CB_ACTIVATE_CMD);
327 
328 	wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock);
329 
330 	qdf_atomic_clear_bit(CMD_MARKED_FOR_ACTIVATION,
331 			     &cmd_list->cmd_in_use);
332 	qdf_atomic_set_bit(CMD_IS_ACTIVE,
333 			   &cmd_list->cmd_in_use);
334 
335 	wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
336 
337 	if (QDF_IS_STATUS_ERROR(status)) {
338 		wlan_serialization_dequeue_cmd(&cmd_list->cmd,
339 					       SER_ACTIVATION_FAILED,
340 					       true);
341 		return status;
342 	}
343 
344 	/*
345 	 * Cmd was marked for activation and delete or cancel
346 	 * is received before activation completed, then the command
347 	 * should be immediately removed after activation
348 	 */
349 	if (qdf_atomic_test_bit(CMD_ACTIVE_MARKED_FOR_REMOVAL,
350 				&cmd_list->cmd_in_use)) {
351 		wlan_serialization_dequeue_cmd(&cmd_list->cmd,
352 					       SER_REMOVE,
353 					       true);
354 		return status;
355 	}
356 
357 	if (qdf_atomic_test_bit(CMD_ACTIVE_MARKED_FOR_CANCEL,
358 				&cmd_list->cmd_in_use))
359 		wlan_serialization_cmd_cancel_handler(
360 				ser_pdev_obj, &cmd_list->cmd,
361 				NULL, NULL, cmd_list->cmd.cmd_type,
362 				WLAN_SERIALIZATION_ACTIVE_QUEUE);
363 error:
364 	return status;
365 }
366 
367 bool
368 wlan_serialization_is_active_cmd_allowed(struct wlan_serialization_command *cmd)
369 {
370 	struct wlan_objmgr_pdev *pdev;
371 	bool active_cmd_allowed = 0;
372 
373 	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
374 	if (!pdev) {
375 		ser_err("NULL pdev");
376 		goto error;
377 	}
378 
379 	if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN)
380 		active_cmd_allowed =
381 		(wlan_serialization_is_active_scan_cmd_allowed(cmd) &&
382 			wlan_serialization_is_scan_pending_queue_empty(cmd));
383 	else
384 		active_cmd_allowed =
385 		(wlan_serialization_is_active_non_scan_cmd_allowed(cmd) &&
386 		 wlan_serialization_is_non_scan_pending_queue_empty(cmd));
387 
388 	ser_debug("active cmd_type[%d] cmd_id[%d] allowed: %d",
389 		  cmd->cmd_type,
390 		  cmd->cmd_id,
391 		  active_cmd_allowed);
392 
393 error:
394 	return active_cmd_allowed;
395 }
396 
397 enum wlan_serialization_status
398 wlan_serialization_move_pending_to_active(
399 		enum wlan_serialization_cmd_type cmd_type,
400 		struct wlan_ser_pdev_obj *ser_pdev_obj,
401 		struct wlan_objmgr_vdev *vdev,
402 		bool blocking_cmd_removed)
403 {
404 	enum wlan_serialization_status status;
405 
406 	if (cmd_type < WLAN_SER_CMD_NONSCAN) {
407 		status =
408 		wlan_ser_move_scan_pending_to_active(
409 				ser_pdev_obj);
410 	} else {
411 		status =
412 		wlan_ser_move_non_scan_pending_to_active(
413 				ser_pdev_obj,
414 				vdev,
415 				blocking_cmd_removed);
416 	}
417 
418 	return status;
419 }
420 
421 enum wlan_serialization_cmd_status
422 wlan_serialization_dequeue_cmd(struct wlan_serialization_command *cmd,
423 			       enum ser_queue_reason ser_reason,
424 			       uint8_t active_cmd)
425 {
426 	enum wlan_serialization_cmd_status status =
427 		WLAN_SER_CMD_NOT_FOUND;
428 	enum wlan_serialization_status ser_status =
429 		WLAN_SER_CMD_DENIED_UNSPECIFIED;
430 
431 	QDF_STATUS qdf_status;
432 	struct wlan_objmgr_pdev *pdev;
433 	struct wlan_objmgr_psoc *psoc;
434 	struct wlan_ser_pdev_obj *ser_pdev_obj;
435 	struct wlan_serialization_command cmd_bkup;
436 	struct wlan_serialization_command_list *cmd_list;
437 	struct wlan_serialization_pdev_queue *pdev_queue;
438 	bool blocking_cmd_removed = 0;
439 
440 	ser_enter();
441 
442 	if (!cmd) {
443 		ser_err("NULL command");
444 		goto error;
445 	}
446 
447 	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
448 	if (!pdev) {
449 		ser_err("invalid pdev");
450 		goto error;
451 	}
452 
453 	psoc = wlan_pdev_get_psoc(pdev);
454 	if (!psoc) {
455 		ser_err("invalid psoc");
456 		goto error;
457 	}
458 
459 	ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev);
460 	if (!ser_pdev_obj) {
461 		ser_err("ser_pdev_obj is empty");
462 		goto error;
463 	}
464 
465 	pdev_queue = wlan_serialization_get_pdev_queue_obj(
466 			ser_pdev_obj, cmd->cmd_type);
467 
468 	ser_debug("dequeue cmd: type[%d] id[%d] high_priority[%d] blocking[%d]",
469 		  cmd->cmd_type,
470 		  cmd->cmd_id,
471 		  cmd->is_high_priority,
472 		  cmd->is_blocking);
473 
474 	wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock);
475 
476 	if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN)
477 		qdf_status = wlan_ser_remove_scan_cmd(
478 				ser_pdev_obj, &cmd_list, cmd, active_cmd);
479 	else {
480 		qdf_status = wlan_ser_remove_non_scan_cmd(
481 				ser_pdev_obj, &cmd_list, cmd, active_cmd);
482 	}
483 
484 	if (qdf_status == QDF_STATUS_E_PENDING) {
485 		status = WLAN_SER_CMD_MARKED_FOR_ACTIVATION;
486 		wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
487 		goto error;
488 	}
489 
490 	if (qdf_status != QDF_STATUS_SUCCESS) {
491 		wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
492 		status = WLAN_SER_CMD_NOT_FOUND;
493 		goto error;
494 	}
495 
496 	if (active_cmd) {
497 		if (cmd_list->cmd.cmd_type >= WLAN_SER_CMD_NONSCAN)
498 			blocking_cmd_removed = cmd_list->cmd.is_blocking;
499 	}
500 
501 	if (active_cmd)
502 		wlan_serialization_find_and_stop_timer(psoc, &cmd_list->cmd);
503 
504 	qdf_mem_copy(&cmd_bkup, &cmd_list->cmd,
505 		     sizeof(struct wlan_serialization_command));
506 	qdf_mem_zero(&cmd_list->cmd,
507 		     sizeof(struct wlan_serialization_command));
508 	cmd_list->cmd_in_use = 0;
509 	qdf_status = wlan_serialization_insert_back(
510 			&pdev_queue->cmd_pool_list,
511 			&cmd_list->pdev_node);
512 
513 	wlan_ser_update_cmd_history(pdev_queue, &cmd_bkup, ser_reason,
514 				    false, active_cmd);
515 
516 	wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
517 
518 	/* Call cmd cb for remove request*/
519 	if (cmd_bkup.cmd_cb) {
520 		/* caller should release the memory */
521 		ser_debug("cmd cb: type[%d] id[%d]: reason: %s",
522 			  cmd_bkup.cmd_type,
523 			  cmd_bkup.cmd_id,
524 			  "WLAN_SER_CB_RELEASE_MEM_CMD");
525 		cmd_bkup.cmd_cb(&cmd_bkup,
526 				     WLAN_SER_CB_RELEASE_MEM_CMD);
527 	}
528 
529 	if (active_cmd) {
530 		ser_status = wlan_serialization_move_pending_to_active(
531 			cmd_bkup.cmd_type, ser_pdev_obj,
532 			cmd_bkup.vdev,
533 			blocking_cmd_removed);
534 	}
535 
536 	if (active_cmd)
537 		status = WLAN_SER_CMD_IN_ACTIVE_LIST;
538 	else
539 		status = WLAN_SER_CMD_IN_PENDING_LIST;
540 
541 error:
542 	ser_exit();
543 	return status;
544 }
545 
546 void wlan_serialization_generic_timer_cb(void *arg)
547 {
548 	struct wlan_serialization_timer *timer = arg;
549 	struct wlan_serialization_command *cmd = timer->cmd;
550 
551 	if (!cmd) {
552 		ser_err("command not found");
553 		QDF_ASSERT(0);
554 		return;
555 	}
556 
557 	ser_err("active cmd timeout for cmd_type[%d] vdev[%pK]",
558 		cmd->cmd_type, cmd->vdev);
559 
560 	if (cmd->cmd_cb)
561 		cmd->cmd_cb(cmd, WLAN_SER_CB_ACTIVE_CMD_TIMEOUT);
562 
563 	/*
564 	 * dequeue cmd API will cleanup and destroy the timer. If it fails to
565 	 * dequeue command then we have to destroy the timer.
566 	 */
567 	wlan_serialization_dequeue_cmd(cmd, SER_TIMEOUT, true);
568 }
569 
570 static QDF_STATUS wlan_serialization_mc_flush_noop(struct scheduler_msg *msg)
571 {
572 	return QDF_STATUS_SUCCESS;
573 }
574 
575 static void
576 wlan_serialization_timer_cb_mc_ctx(void *arg)
577 {
578 	struct scheduler_msg msg = {0};
579 
580 	msg.type = SYS_MSG_ID_MC_TIMER;
581 	msg.reserved = SYS_MSG_COOKIE;
582 	msg.callback = wlan_serialization_generic_timer_cb;
583 	msg.bodyptr = arg;
584 	msg.bodyval = 0;
585 	msg.flush_callback = wlan_serialization_mc_flush_noop;
586 
587 	if (scheduler_post_msg(QDF_MODULE_ID_SYS, &msg) == QDF_STATUS_SUCCESS)
588 		return;
589 
590 	ser_err("Could not enqueue timer to timer queue");
591 }
592 
593 #ifdef CONFIG_MCL
594 static void wlan_serialization_timer_handler(void *arg)
595 {
596 	ser_enter();
597 
598 	wlan_serialization_timer_cb_mc_ctx(arg);
599 
600 	ser_exit();
601 }
602 #else
603 static void wlan_serialization_timer_handler(void *arg)
604 {
605 	struct wlan_serialization_timer *timer = arg;
606 	struct wlan_serialization_command *cmd = timer->cmd;
607 
608 	if (!cmd) {
609 		ser_err("command not found");
610 		QDF_ASSERT(0);
611 		return;
612 	}
613 
614 	if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN)
615 		wlan_serialization_timer_cb_mc_ctx(arg);
616 	else
617 		wlan_serialization_generic_timer_cb(arg);
618 }
619 #endif
620 
621 QDF_STATUS
622 wlan_serialization_find_and_update_timer(
623 		struct wlan_objmgr_psoc *psoc,
624 		struct wlan_serialization_command *cmd)
625 {
626 	struct wlan_ser_psoc_obj *psoc_ser_obj;
627 	struct wlan_serialization_timer *ser_timer;
628 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
629 	int i = 0;
630 
631 	if (!psoc || !cmd) {
632 		ser_err("invalid param");
633 		goto exit;
634 	}
635 
636 	psoc_ser_obj = wlan_serialization_get_psoc_obj(psoc);
637 	/*
638 	 * Here cmd_id and cmd_type are used to locate the timer being
639 	 * associated with command.
640 	 */
641 	wlan_serialization_acquire_lock(&psoc_ser_obj->timer_lock);
642 
643 	for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) {
644 		ser_timer = &psoc_ser_obj->timers[i];
645 		if (!(ser_timer->cmd) ||
646 		    (ser_timer->cmd->cmd_id != cmd->cmd_id) ||
647 		    (ser_timer->cmd->cmd_type != cmd->cmd_type) ||
648 		    (ser_timer->cmd->vdev != cmd->vdev))
649 			continue;
650 
651 		qdf_timer_mod(&ser_timer->timer,
652 			      cmd->cmd_timeout_duration);
653 		status = QDF_STATUS_SUCCESS;
654 		break;
655 	}
656 
657 	wlan_serialization_release_lock(&psoc_ser_obj->timer_lock);
658 
659 	if (QDF_IS_STATUS_SUCCESS(status))
660 		ser_debug("Updated the timer for cmd type:%d, id: %d",
661 			  cmd->cmd_type, cmd->cmd_id);
662 	else
663 		ser_err("Can't find timer for cmd_type[%d]", cmd->cmd_type);
664 
665 exit:
666 	return status;
667 }
668 
669 QDF_STATUS
670 wlan_serialization_find_and_stop_timer(struct wlan_objmgr_psoc *psoc,
671 				       struct wlan_serialization_command *cmd)
672 {
673 	struct wlan_ser_psoc_obj *psoc_ser_obj;
674 	struct wlan_serialization_timer *ser_timer;
675 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
676 	int i = 0;
677 	uint32_t phy_version;
678 
679 	if (!psoc || !cmd) {
680 		ser_err("invalid param");
681 		goto exit;
682 	}
683 
684 	if (cmd->cmd_timeout_duration == 0) {
685 		phy_version = wlan_psoc_get_nif_phy_version(psoc);
686 		if (wlan_is_emulation_platform(phy_version)) {
687 			ser_err("[SCAN-EMULATION]: Not performing timer funcs");
688 			status = QDF_STATUS_SUCCESS;
689 		goto exit;
690 		}
691 	}
692 
693 	psoc_ser_obj = wlan_serialization_get_psoc_obj(psoc);
694 	/*
695 	 * Here cmd_id and cmd_type are used to locate the timer being
696 	 * associated with command.
697 	 */
698 	wlan_serialization_acquire_lock(&psoc_ser_obj->timer_lock);
699 
700 	for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) {
701 		ser_timer = &psoc_ser_obj->timers[i];
702 		if (!(ser_timer->cmd) ||
703 		    (ser_timer->cmd->cmd_id != cmd->cmd_id) ||
704 		    (ser_timer->cmd->cmd_type != cmd->cmd_type) ||
705 		    (ser_timer->cmd->vdev != cmd->vdev))
706 			continue;
707 
708 		status = wlan_serialization_stop_timer(ser_timer);
709 		break;
710 	}
711 
712 	wlan_serialization_release_lock(&psoc_ser_obj->timer_lock);
713 
714 	if (QDF_IS_STATUS_SUCCESS(status))
715 		ser_debug("Stopped timer for cmd_type %d cmd id %d",
716 			  cmd->cmd_type, cmd->cmd_id);
717 	else
718 		ser_err("Can't find timer for cmd_type %d cmd id %d",
719 			cmd->cmd_type, cmd->cmd_id);
720 
721 exit:
722 	return status;
723 }
724 
725 QDF_STATUS
726 wlan_serialization_find_and_start_timer(struct wlan_objmgr_psoc *psoc,
727 					struct wlan_serialization_command *cmd)
728 {
729 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
730 	struct wlan_ser_psoc_obj *psoc_ser_obj;
731 	struct wlan_serialization_timer *ser_timer;
732 	int i = 0;
733 	uint32_t nif_phy_ver;
734 
735 	if (!psoc || !cmd) {
736 		ser_err("invalid param");
737 		goto error;
738 	}
739 
740 	nif_phy_ver = wlan_psoc_get_nif_phy_version(psoc);
741 	if ((cmd->cmd_timeout_duration == 0) &&
742 	    (wlan_is_emulation_platform(nif_phy_ver))) {
743 		ser_err("[SCAN-EMULATION]: Not performing timer functions\n");
744 		status = QDF_STATUS_SUCCESS;
745 		goto exit;
746 	}
747 
748 	psoc_ser_obj = wlan_serialization_get_psoc_obj(psoc);
749 
750 	wlan_serialization_acquire_lock(&psoc_ser_obj->timer_lock);
751 
752 	for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) {
753 		/* Keep trying timer */
754 		ser_timer = &psoc_ser_obj->timers[i];
755 		if (ser_timer->cmd)
756 			continue;
757 
758 		/* Remember timer is pointing to command */
759 		ser_timer->cmd = cmd;
760 		status = QDF_STATUS_SUCCESS;
761 		break;
762 	}
763 
764 	wlan_serialization_release_lock(&psoc_ser_obj->timer_lock);
765 
766 	if (QDF_IS_STATUS_SUCCESS(status)) {
767 		qdf_timer_init(NULL,
768 			       &ser_timer->timer,
769 			       wlan_serialization_timer_handler,
770 			       ser_timer,
771 			       QDF_TIMER_TYPE_SW);
772 			       qdf_timer_mod(&ser_timer->timer,
773 			       cmd->cmd_timeout_duration);
774 
775 		ser_debug("starting timer for cmd: type[%d] id[%d] high_priority[%d] blocking[%d]",
776 			  cmd->cmd_type,
777 			  cmd->cmd_id,
778 			  cmd->is_high_priority,
779 			  cmd->is_blocking);
780 	}
781 
782 error:
783 exit:
784 
785 	return status;
786 }
787 
788 enum wlan_serialization_cmd_status
789 wlan_serialization_cmd_cancel_handler(
790 		struct wlan_ser_pdev_obj *ser_obj,
791 		struct wlan_serialization_command *cmd,
792 		struct wlan_objmgr_pdev *pdev, struct wlan_objmgr_vdev *vdev,
793 		enum wlan_serialization_cmd_type cmd_type, uint8_t queue_type)
794 {
795 	enum wlan_serialization_cmd_status active_status =
796 		WLAN_SER_CMD_NOT_FOUND;
797 	enum wlan_serialization_cmd_status pending_status =
798 		WLAN_SER_CMD_NOT_FOUND;
799 	enum wlan_serialization_cmd_status status =
800 		WLAN_SER_CMD_NOT_FOUND;
801 
802 	ser_enter();
803 
804 	if (!ser_obj) {
805 		ser_err("invalid serial object");
806 		goto error;
807 	}
808 
809 	if (queue_type & WLAN_SERIALIZATION_ACTIVE_QUEUE) {
810 		if (cmd_type < WLAN_SER_CMD_NONSCAN)
811 			active_status = wlan_ser_cancel_scan_cmd(
812 					ser_obj, pdev, vdev, cmd,
813 					cmd_type, true);
814 		else
815 			active_status = wlan_ser_cancel_non_scan_cmd(
816 					ser_obj, pdev, vdev, cmd,
817 					cmd_type, true);
818 	}
819 
820 	if (queue_type & WLAN_SERIALIZATION_PENDING_QUEUE) {
821 		if (cmd_type < WLAN_SER_CMD_NONSCAN)
822 			pending_status = wlan_ser_cancel_scan_cmd(
823 					ser_obj, pdev, vdev, cmd,
824 					cmd_type, false);
825 		else
826 			pending_status = wlan_ser_cancel_non_scan_cmd(
827 					ser_obj, pdev, vdev, cmd,
828 					cmd_type, false);
829 	}
830 
831 	if (active_status == WLAN_SER_CMD_IN_ACTIVE_LIST &&
832 	    pending_status == WLAN_SER_CMD_IN_PENDING_LIST)
833 		status = WLAN_SER_CMDS_IN_ALL_LISTS;
834 	else if (active_status == WLAN_SER_CMD_IN_ACTIVE_LIST)
835 		status = active_status;
836 	else if (pending_status == WLAN_SER_CMD_IN_PENDING_LIST)
837 		status = pending_status;
838 
839 error:
840 	ser_exit();
841 	return status;
842 }
843 
844 enum wlan_serialization_cmd_status
845 wlan_serialization_find_and_cancel_cmd(
846 		struct wlan_serialization_command *cmd,
847 		enum wlan_serialization_cancel_type req_type,
848 		uint8_t queue_type)
849 {
850 	enum wlan_serialization_cmd_status status = WLAN_SER_CMD_NOT_FOUND;
851 	struct wlan_ser_pdev_obj *ser_obj = NULL;
852 	struct wlan_objmgr_pdev *pdev;
853 
854 	ser_enter();
855 
856 	if (!cmd) {
857 		ser_err("Invalid cmd");
858 		goto error;
859 	}
860 
861 	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
862 	if (!pdev) {
863 		ser_err("Invalid pdev");
864 		goto error;
865 	}
866 	ser_obj = wlan_serialization_get_pdev_obj(pdev);
867 	if (!ser_obj) {
868 		ser_err("Invalid ser_obj");
869 		goto error;
870 	}
871 
872 	switch (req_type) {
873 	case WLAN_SER_CANCEL_SINGLE_SCAN:
874 		/* remove scan cmd which matches the given cmd struct */
875 		status = wlan_serialization_cmd_cancel_handler(
876 				ser_obj, cmd, NULL, NULL,
877 				WLAN_SER_CMD_SCAN, queue_type);
878 		break;
879 	case WLAN_SER_CANCEL_PDEV_SCANS:
880 		/* remove all scan cmds which matches the pdev object */
881 		status = wlan_serialization_cmd_cancel_handler(
882 				ser_obj, NULL, pdev, NULL,
883 				WLAN_SER_CMD_SCAN, queue_type);
884 		break;
885 	case WLAN_SER_CANCEL_VDEV_SCANS:
886 		/* remove all scan cmds which matches the vdev object */
887 		status = wlan_serialization_cmd_cancel_handler(
888 				ser_obj, NULL, NULL, cmd->vdev,
889 				WLAN_SER_CMD_SCAN, queue_type);
890 		break;
891 	case WLAN_SER_CANCEL_NON_SCAN_CMD:
892 		/* remove nonscan cmd which matches the given cmd */
893 		status = wlan_serialization_cmd_cancel_handler(
894 				ser_obj, cmd, NULL, NULL,
895 				WLAN_SER_CMD_NONSCAN, queue_type);
896 		break;
897 	case WLAN_SER_CANCEL_PDEV_NON_SCAN_CMD:
898 		/* remove all non scan cmds which matches the pdev object */
899 		status = wlan_serialization_cmd_cancel_handler(
900 				ser_obj, NULL, pdev, NULL,
901 				WLAN_SER_CMD_NONSCAN, queue_type);
902 		break;
903 	case WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD:
904 		/* remove all non scan cmds which matches the vdev object */
905 		status = wlan_serialization_cmd_cancel_handler(
906 				ser_obj, NULL, NULL, cmd->vdev,
907 				WLAN_SER_CMD_NONSCAN, queue_type);
908 		break;
909 	case WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE:
910 		/*
911 		 * remove all non scan cmds which matches the vdev
912 		 * and given cmd type
913 		 */
914 		status = wlan_serialization_cmd_cancel_handler(
915 				ser_obj, NULL, NULL, cmd->vdev,
916 				cmd->cmd_type, queue_type);
917 		break;
918 	default:
919 		ser_err("Invalid request");
920 	}
921 
922 error:
923 	ser_exit();
924 	return status;
925 }
926