xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_internal.c (revision 8ddef7dd9a290d4a9b1efd5d3efacf51d78a1a0d)
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 		cmd_list->cmd_in_use = 0;
260 		wlan_serialization_insert_back(
261 			&pdev_queue->cmd_pool_list,
262 			&cmd_list->pdev_node);
263 		wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
264 		ser_err("Failed to add cmd to active/pending queue");
265 		goto error;
266 	}
267 
268 	if (WLAN_SER_CMD_ACTIVE == status) {
269 		qdf_atomic_set_bit(CMD_MARKED_FOR_ACTIVATION,
270 				   &cmd_list->cmd_in_use);
271 	}
272 
273 	wlan_ser_update_cmd_history(pdev_queue, &cmd_list->cmd,
274 				    ser_reason, true, active_queue);
275 
276 	wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
277 
278 	if (WLAN_SER_CMD_ACTIVE == status)
279 		wlan_serialization_activate_cmd(cmd_list,
280 						ser_pdev_obj, ser_reason);
281 
282 error:
283 	ser_exit();
284 
285 	return status;
286 }
287 
288 QDF_STATUS wlan_serialization_activate_cmd(
289 			struct wlan_serialization_command_list *cmd_list,
290 			struct wlan_ser_pdev_obj *ser_pdev_obj,
291 			enum ser_queue_reason ser_reason)
292 {
293 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
294 	struct wlan_objmgr_psoc *psoc = NULL;
295 	struct wlan_serialization_pdev_queue *pdev_queue;
296 
297 	pdev_queue = wlan_serialization_get_pdev_queue_obj(
298 			ser_pdev_obj, cmd_list->cmd.cmd_type);
299 
300 	psoc = wlan_vdev_get_psoc(cmd_list->cmd.vdev);
301 	if (!psoc) {
302 		ser_err("invalid psoc");
303 		goto error;
304 	}
305 
306 	/*
307 	 * command is already pushed to active queue above
308 	 * now start the timer and notify requestor
309 	 */
310 	wlan_serialization_find_and_start_timer(psoc, &cmd_list->cmd);
311 	/*
312 	 * Remember that serialization module may send
313 	 * this callback in same context through which it
314 	 * received the serialization request. Due to which
315 	 * it is caller's responsibility to ensure acquiring
316 	 * and releasing its own lock appropriately.
317 	 */
318 
319 	ser_debug("cmd cb: type[%d] id[%d] : reason: %s",
320 		  cmd_list->cmd.cmd_type,
321 		  cmd_list->cmd.cmd_id,
322 		  "WLAN_SER_CB_ACTIVATE_CMD");
323 
324 	cmd_list->cmd.activation_reason = ser_reason;
325 
326 	status = cmd_list->cmd.cmd_cb(&cmd_list->cmd,
327 				WLAN_SER_CB_ACTIVATE_CMD);
328 
329 	wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock);
330 
331 	qdf_atomic_clear_bit(CMD_MARKED_FOR_ACTIVATION,
332 			     &cmd_list->cmd_in_use);
333 	qdf_atomic_set_bit(CMD_IS_ACTIVE,
334 			   &cmd_list->cmd_in_use);
335 
336 	wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
337 
338 	if (QDF_IS_STATUS_ERROR(status)) {
339 		wlan_serialization_dequeue_cmd(&cmd_list->cmd,
340 					       SER_ACTIVATION_FAILED,
341 					       true);
342 		return status;
343 	}
344 
345 	/*
346 	 * Cmd was marked for activation and delete or cancel
347 	 * is received before activation completed, then the command
348 	 * should be immediately removed after activation
349 	 */
350 	if (qdf_atomic_test_bit(CMD_ACTIVE_MARKED_FOR_REMOVAL,
351 				&cmd_list->cmd_in_use)) {
352 		wlan_serialization_dequeue_cmd(&cmd_list->cmd,
353 					       SER_REMOVE,
354 					       true);
355 		return status;
356 	}
357 
358 	if (qdf_atomic_test_bit(CMD_ACTIVE_MARKED_FOR_CANCEL,
359 				&cmd_list->cmd_in_use))
360 		wlan_serialization_cmd_cancel_handler(
361 				ser_pdev_obj, &cmd_list->cmd,
362 				NULL, NULL, cmd_list->cmd.cmd_type,
363 				WLAN_SERIALIZATION_ACTIVE_QUEUE);
364 error:
365 	return status;
366 }
367 
368 bool
369 wlan_serialization_is_active_cmd_allowed(struct wlan_serialization_command *cmd)
370 {
371 	struct wlan_objmgr_pdev *pdev;
372 	bool active_cmd_allowed = 0;
373 
374 	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
375 	if (!pdev) {
376 		ser_err("NULL pdev");
377 		goto error;
378 	}
379 
380 	if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN)
381 		active_cmd_allowed =
382 		(wlan_serialization_is_active_scan_cmd_allowed(cmd) &&
383 			wlan_serialization_is_scan_pending_queue_empty(cmd));
384 	else
385 		active_cmd_allowed =
386 		(wlan_serialization_is_active_non_scan_cmd_allowed(cmd) &&
387 		 wlan_serialization_is_non_scan_pending_queue_empty(cmd));
388 
389 	ser_debug("active cmd_type[%d] cmd_id[%d] allowed: %d",
390 		  cmd->cmd_type,
391 		  cmd->cmd_id,
392 		  active_cmd_allowed);
393 
394 error:
395 	return active_cmd_allowed;
396 }
397 
398 enum wlan_serialization_status
399 wlan_serialization_move_pending_to_active(
400 		enum wlan_serialization_cmd_type cmd_type,
401 		struct wlan_ser_pdev_obj *ser_pdev_obj,
402 		struct wlan_objmgr_vdev *vdev,
403 		bool blocking_cmd_removed)
404 {
405 	enum wlan_serialization_status status;
406 
407 	if (cmd_type < WLAN_SER_CMD_NONSCAN) {
408 		status =
409 		wlan_ser_move_scan_pending_to_active(
410 				ser_pdev_obj);
411 	} else {
412 		status =
413 		wlan_ser_move_non_scan_pending_to_active(
414 				ser_pdev_obj,
415 				vdev,
416 				blocking_cmd_removed);
417 	}
418 
419 	return status;
420 }
421 
422 enum wlan_serialization_cmd_status
423 wlan_serialization_dequeue_cmd(struct wlan_serialization_command *cmd,
424 			       enum ser_queue_reason ser_reason,
425 			       uint8_t active_cmd)
426 {
427 	enum wlan_serialization_cmd_status status =
428 		WLAN_SER_CMD_NOT_FOUND;
429 	enum wlan_serialization_status ser_status =
430 		WLAN_SER_CMD_DENIED_UNSPECIFIED;
431 
432 	QDF_STATUS qdf_status;
433 	struct wlan_objmgr_pdev *pdev;
434 	struct wlan_objmgr_psoc *psoc;
435 	struct wlan_ser_pdev_obj *ser_pdev_obj;
436 	struct wlan_serialization_command cmd_bkup;
437 	struct wlan_serialization_command_list *cmd_list;
438 	struct wlan_serialization_pdev_queue *pdev_queue;
439 	bool blocking_cmd_removed = 0;
440 
441 	ser_enter();
442 
443 	if (!cmd) {
444 		ser_err("NULL command");
445 		goto error;
446 	}
447 
448 	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
449 	if (!pdev) {
450 		ser_err("invalid pdev");
451 		goto error;
452 	}
453 
454 	psoc = wlan_pdev_get_psoc(pdev);
455 	if (!psoc) {
456 		ser_err("invalid psoc");
457 		goto error;
458 	}
459 
460 	ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev);
461 	if (!ser_pdev_obj) {
462 		ser_err("ser_pdev_obj is empty");
463 		goto error;
464 	}
465 
466 	pdev_queue = wlan_serialization_get_pdev_queue_obj(
467 			ser_pdev_obj, cmd->cmd_type);
468 
469 	ser_debug("dequeue cmd: type[%d] id[%d] high_priority[%d] blocking[%d]",
470 		  cmd->cmd_type,
471 		  cmd->cmd_id,
472 		  cmd->is_high_priority,
473 		  cmd->is_blocking);
474 
475 	wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock);
476 
477 	if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN)
478 		qdf_status = wlan_ser_remove_scan_cmd(
479 				ser_pdev_obj, &cmd_list, cmd, active_cmd);
480 	else {
481 		qdf_status = wlan_ser_remove_non_scan_cmd(
482 				ser_pdev_obj, &cmd_list, cmd, active_cmd);
483 	}
484 
485 	if (qdf_status == QDF_STATUS_E_PENDING) {
486 		status = WLAN_SER_CMD_MARKED_FOR_ACTIVATION;
487 		wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
488 		goto error;
489 	}
490 
491 	if (qdf_status != QDF_STATUS_SUCCESS) {
492 		wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
493 		status = WLAN_SER_CMD_NOT_FOUND;
494 		goto error;
495 	}
496 
497 	if (active_cmd) {
498 		if (cmd_list->cmd.cmd_type >= WLAN_SER_CMD_NONSCAN)
499 			blocking_cmd_removed = cmd_list->cmd.is_blocking;
500 	}
501 
502 	if (active_cmd)
503 		wlan_serialization_find_and_stop_timer(psoc, &cmd_list->cmd);
504 
505 	qdf_mem_copy(&cmd_bkup, &cmd_list->cmd,
506 		     sizeof(struct wlan_serialization_command));
507 	qdf_mem_zero(&cmd_list->cmd,
508 		     sizeof(struct wlan_serialization_command));
509 	cmd_list->cmd_in_use = 0;
510 	qdf_status = wlan_serialization_insert_back(
511 			&pdev_queue->cmd_pool_list,
512 			&cmd_list->pdev_node);
513 
514 	wlan_ser_update_cmd_history(pdev_queue, &cmd_bkup, ser_reason,
515 				    false, active_cmd);
516 
517 	wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
518 
519 	/* Call cmd cb for remove request*/
520 	if (cmd_bkup.cmd_cb) {
521 		/* caller should release the memory */
522 		ser_debug("cmd cb: type[%d] id[%d]: reason: %s",
523 			  cmd_bkup.cmd_type,
524 			  cmd_bkup.cmd_id,
525 			  "WLAN_SER_CB_RELEASE_MEM_CMD");
526 		cmd_bkup.cmd_cb(&cmd_bkup,
527 				     WLAN_SER_CB_RELEASE_MEM_CMD);
528 	}
529 
530 	if (active_cmd) {
531 		ser_status = wlan_serialization_move_pending_to_active(
532 			cmd_bkup.cmd_type, ser_pdev_obj,
533 			cmd_bkup.vdev,
534 			blocking_cmd_removed);
535 	}
536 
537 	if (active_cmd)
538 		status = WLAN_SER_CMD_IN_ACTIVE_LIST;
539 	else
540 		status = WLAN_SER_CMD_IN_PENDING_LIST;
541 
542 error:
543 	ser_exit();
544 	return status;
545 }
546 
547 void wlan_serialization_generic_timer_cb(void *arg)
548 {
549 	struct wlan_serialization_timer *timer = arg;
550 	struct wlan_serialization_command *cmd = timer->cmd;
551 
552 	if (!cmd) {
553 		ser_err("command not found");
554 		QDF_ASSERT(0);
555 		return;
556 	}
557 
558 	ser_err("active cmd timeout for cmd_type[%d] vdev[%pK]",
559 		cmd->cmd_type, cmd->vdev);
560 
561 	if (cmd->cmd_cb)
562 		cmd->cmd_cb(cmd, WLAN_SER_CB_ACTIVE_CMD_TIMEOUT);
563 
564 	/*
565 	 * dequeue cmd API will cleanup and destroy the timer. If it fails to
566 	 * dequeue command then we have to destroy the timer.
567 	 */
568 	wlan_serialization_dequeue_cmd(cmd, SER_TIMEOUT, true);
569 }
570 
571 static QDF_STATUS wlan_serialization_mc_flush_noop(struct scheduler_msg *msg)
572 {
573 	return QDF_STATUS_SUCCESS;
574 }
575 
576 static void
577 wlan_serialization_timer_cb_mc_ctx(void *arg)
578 {
579 	struct scheduler_msg msg = {0};
580 
581 	msg.type = SYS_MSG_ID_MC_TIMER;
582 	msg.reserved = SYS_MSG_COOKIE;
583 	msg.callback = wlan_serialization_generic_timer_cb;
584 	msg.bodyptr = arg;
585 	msg.bodyval = 0;
586 	msg.flush_callback = wlan_serialization_mc_flush_noop;
587 
588 	if (scheduler_post_message(QDF_MODULE_ID_SERIALIZATION,
589 				   QDF_MODULE_ID_SERIALIZATION,
590 				   QDF_MODULE_ID_SYS, &msg) ==
591 							QDF_STATUS_SUCCESS)
592 		return;
593 
594 	ser_err("Could not enqueue timer to timer queue");
595 }
596 
597 #ifdef CONFIG_MCL
598 static void wlan_serialization_timer_handler(void *arg)
599 {
600 	ser_enter();
601 
602 	wlan_serialization_timer_cb_mc_ctx(arg);
603 
604 	ser_exit();
605 }
606 #else
607 static void wlan_serialization_timer_handler(void *arg)
608 {
609 	struct wlan_serialization_timer *timer = arg;
610 	struct wlan_serialization_command *cmd = timer->cmd;
611 
612 	if (!cmd) {
613 		ser_err("command not found");
614 		QDF_ASSERT(0);
615 		return;
616 	}
617 
618 	if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN)
619 		wlan_serialization_timer_cb_mc_ctx(arg);
620 	else
621 		wlan_serialization_generic_timer_cb(arg);
622 }
623 #endif
624 
625 QDF_STATUS
626 wlan_serialization_find_and_update_timer(
627 		struct wlan_objmgr_psoc *psoc,
628 		struct wlan_serialization_command *cmd)
629 {
630 	struct wlan_ser_psoc_obj *psoc_ser_obj;
631 	struct wlan_serialization_timer *ser_timer;
632 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
633 	int i = 0;
634 
635 	if (!psoc || !cmd) {
636 		ser_err("invalid param");
637 		goto exit;
638 	}
639 
640 	psoc_ser_obj = wlan_serialization_get_psoc_obj(psoc);
641 	/*
642 	 * Here cmd_id and cmd_type are used to locate the timer being
643 	 * associated with command.
644 	 */
645 	wlan_serialization_acquire_lock(&psoc_ser_obj->timer_lock);
646 
647 	for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) {
648 		ser_timer = &psoc_ser_obj->timers[i];
649 		if (!(ser_timer->cmd) ||
650 		    (ser_timer->cmd->cmd_id != cmd->cmd_id) ||
651 		    (ser_timer->cmd->cmd_type != cmd->cmd_type) ||
652 		    (ser_timer->cmd->vdev != cmd->vdev))
653 			continue;
654 
655 		qdf_timer_mod(&ser_timer->timer,
656 			      cmd->cmd_timeout_duration);
657 		status = QDF_STATUS_SUCCESS;
658 		break;
659 	}
660 
661 	wlan_serialization_release_lock(&psoc_ser_obj->timer_lock);
662 
663 	if (QDF_IS_STATUS_SUCCESS(status))
664 		ser_debug("Updated the timer for cmd type:%d, id: %d",
665 			  cmd->cmd_type, cmd->cmd_id);
666 	else
667 		ser_err("Can't find timer for cmd_type[%d]", cmd->cmd_type);
668 
669 exit:
670 	return status;
671 }
672 
673 QDF_STATUS
674 wlan_serialization_find_and_stop_timer(struct wlan_objmgr_psoc *psoc,
675 				       struct wlan_serialization_command *cmd)
676 {
677 	struct wlan_ser_psoc_obj *psoc_ser_obj;
678 	struct wlan_serialization_timer *ser_timer;
679 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
680 	int i = 0;
681 	uint32_t phy_version;
682 
683 	if (!psoc || !cmd) {
684 		ser_err("invalid param");
685 		goto exit;
686 	}
687 
688 	if (cmd->cmd_timeout_duration == 0) {
689 		phy_version = wlan_psoc_get_nif_phy_version(psoc);
690 		if (wlan_is_emulation_platform(phy_version)) {
691 			ser_err("[SCAN-EMULATION]: Not performing timer funcs");
692 			status = QDF_STATUS_SUCCESS;
693 		goto exit;
694 		}
695 	}
696 
697 	psoc_ser_obj = wlan_serialization_get_psoc_obj(psoc);
698 	/*
699 	 * Here cmd_id and cmd_type are used to locate the timer being
700 	 * associated with command.
701 	 */
702 	wlan_serialization_acquire_lock(&psoc_ser_obj->timer_lock);
703 
704 	for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) {
705 		ser_timer = &psoc_ser_obj->timers[i];
706 		if (!(ser_timer->cmd) ||
707 		    (ser_timer->cmd->cmd_id != cmd->cmd_id) ||
708 		    (ser_timer->cmd->cmd_type != cmd->cmd_type) ||
709 		    (ser_timer->cmd->vdev != cmd->vdev))
710 			continue;
711 
712 		status = wlan_serialization_stop_timer(ser_timer);
713 		break;
714 	}
715 
716 	wlan_serialization_release_lock(&psoc_ser_obj->timer_lock);
717 
718 	if (QDF_IS_STATUS_SUCCESS(status))
719 		ser_debug("Stopped timer for cmd_type %d cmd id %d",
720 			  cmd->cmd_type, cmd->cmd_id);
721 	else
722 		ser_err("Can't find timer for cmd_type %d cmd id %d",
723 			cmd->cmd_type, cmd->cmd_id);
724 
725 exit:
726 	return status;
727 }
728 
729 QDF_STATUS
730 wlan_serialization_find_and_start_timer(struct wlan_objmgr_psoc *psoc,
731 					struct wlan_serialization_command *cmd)
732 {
733 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
734 	struct wlan_ser_psoc_obj *psoc_ser_obj;
735 	struct wlan_serialization_timer *ser_timer;
736 	int i = 0;
737 	uint32_t nif_phy_ver;
738 
739 	if (!psoc || !cmd) {
740 		ser_err("invalid param");
741 		goto error;
742 	}
743 
744 	nif_phy_ver = wlan_psoc_get_nif_phy_version(psoc);
745 	if ((cmd->cmd_timeout_duration == 0) &&
746 	    (wlan_is_emulation_platform(nif_phy_ver))) {
747 		ser_err("[SCAN-EMULATION]: Not performing timer functions\n");
748 		status = QDF_STATUS_SUCCESS;
749 		goto exit;
750 	}
751 
752 	psoc_ser_obj = wlan_serialization_get_psoc_obj(psoc);
753 
754 	wlan_serialization_acquire_lock(&psoc_ser_obj->timer_lock);
755 
756 	for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) {
757 		/* Keep trying timer */
758 		ser_timer = &psoc_ser_obj->timers[i];
759 		if (ser_timer->cmd)
760 			continue;
761 
762 		/* Remember timer is pointing to command */
763 		ser_timer->cmd = cmd;
764 		status = QDF_STATUS_SUCCESS;
765 		break;
766 	}
767 
768 	wlan_serialization_release_lock(&psoc_ser_obj->timer_lock);
769 
770 	if (QDF_IS_STATUS_SUCCESS(status)) {
771 		qdf_timer_init(NULL,
772 			       &ser_timer->timer,
773 			       wlan_serialization_timer_handler,
774 			       ser_timer,
775 			       QDF_TIMER_TYPE_SW);
776 			       qdf_timer_mod(&ser_timer->timer,
777 			       cmd->cmd_timeout_duration);
778 
779 		ser_debug("Started timer for cmd: type[%d] id[%d] high_priority[%d] blocking[%d]",
780 			  cmd->cmd_type,
781 			  cmd->cmd_id,
782 			  cmd->is_high_priority,
783 			  cmd->is_blocking);
784 	} else {
785 		ser_err("Failed to start timer for cmd: type[%d] id[%d] high_priority[%d] blocking[%d]",
786 			  cmd->cmd_type,
787 			  cmd->cmd_id,
788 			  cmd->is_high_priority,
789 			  cmd->is_blocking);
790 	}
791 
792 error:
793 exit:
794 
795 	return status;
796 }
797 
798 enum wlan_serialization_cmd_status
799 wlan_serialization_cmd_cancel_handler(
800 		struct wlan_ser_pdev_obj *ser_obj,
801 		struct wlan_serialization_command *cmd,
802 		struct wlan_objmgr_pdev *pdev, struct wlan_objmgr_vdev *vdev,
803 		enum wlan_serialization_cmd_type cmd_type, uint8_t queue_type)
804 {
805 	enum wlan_serialization_cmd_status active_status =
806 		WLAN_SER_CMD_NOT_FOUND;
807 	enum wlan_serialization_cmd_status pending_status =
808 		WLAN_SER_CMD_NOT_FOUND;
809 	enum wlan_serialization_cmd_status status =
810 		WLAN_SER_CMD_NOT_FOUND;
811 
812 	ser_enter();
813 
814 	if (!ser_obj) {
815 		ser_err("invalid serial object");
816 		goto error;
817 	}
818 
819 	if (queue_type & WLAN_SERIALIZATION_ACTIVE_QUEUE) {
820 		if (cmd_type < WLAN_SER_CMD_NONSCAN)
821 			active_status = wlan_ser_cancel_scan_cmd(
822 					ser_obj, pdev, vdev, cmd,
823 					cmd_type, true);
824 		else
825 			active_status = wlan_ser_cancel_non_scan_cmd(
826 					ser_obj, pdev, vdev, cmd,
827 					cmd_type, true);
828 	}
829 
830 	if (queue_type & WLAN_SERIALIZATION_PENDING_QUEUE) {
831 		if (cmd_type < WLAN_SER_CMD_NONSCAN)
832 			pending_status = wlan_ser_cancel_scan_cmd(
833 					ser_obj, pdev, vdev, cmd,
834 					cmd_type, false);
835 		else
836 			pending_status = wlan_ser_cancel_non_scan_cmd(
837 					ser_obj, pdev, vdev, cmd,
838 					cmd_type, false);
839 	}
840 
841 	if (active_status == WLAN_SER_CMD_IN_ACTIVE_LIST &&
842 	    pending_status == WLAN_SER_CMD_IN_PENDING_LIST)
843 		status = WLAN_SER_CMDS_IN_ALL_LISTS;
844 	else if (active_status == WLAN_SER_CMD_IN_ACTIVE_LIST)
845 		status = active_status;
846 	else if (pending_status == WLAN_SER_CMD_IN_PENDING_LIST)
847 		status = pending_status;
848 
849 error:
850 	ser_exit();
851 	return status;
852 }
853 
854 enum wlan_serialization_cmd_status
855 wlan_serialization_find_and_cancel_cmd(
856 		struct wlan_serialization_command *cmd,
857 		enum wlan_serialization_cancel_type req_type,
858 		uint8_t queue_type)
859 {
860 	enum wlan_serialization_cmd_status status = WLAN_SER_CMD_NOT_FOUND;
861 	struct wlan_ser_pdev_obj *ser_obj = NULL;
862 	struct wlan_objmgr_pdev *pdev;
863 
864 	ser_enter();
865 
866 	if (!cmd) {
867 		ser_err("Invalid cmd");
868 		goto error;
869 	}
870 
871 	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
872 	if (!pdev) {
873 		ser_err("Invalid pdev");
874 		goto error;
875 	}
876 	ser_obj = wlan_serialization_get_pdev_obj(pdev);
877 	if (!ser_obj) {
878 		ser_err("Invalid ser_obj");
879 		goto error;
880 	}
881 
882 	switch (req_type) {
883 	case WLAN_SER_CANCEL_SINGLE_SCAN:
884 		/* remove scan cmd which matches the given cmd struct */
885 		status = wlan_serialization_cmd_cancel_handler(
886 				ser_obj, cmd, NULL, NULL,
887 				WLAN_SER_CMD_SCAN, queue_type);
888 		break;
889 	case WLAN_SER_CANCEL_PDEV_SCANS:
890 		/* remove all scan cmds which matches the pdev object */
891 		status = wlan_serialization_cmd_cancel_handler(
892 				ser_obj, NULL, pdev, NULL,
893 				WLAN_SER_CMD_SCAN, queue_type);
894 		break;
895 	case WLAN_SER_CANCEL_VDEV_SCANS:
896 		/* remove all scan cmds which matches the vdev object */
897 		status = wlan_serialization_cmd_cancel_handler(
898 				ser_obj, NULL, NULL, cmd->vdev,
899 				WLAN_SER_CMD_SCAN, queue_type);
900 		break;
901 	case WLAN_SER_CANCEL_NON_SCAN_CMD:
902 		/* remove nonscan cmd which matches the given cmd */
903 		status = wlan_serialization_cmd_cancel_handler(
904 				ser_obj, cmd, NULL, NULL,
905 				WLAN_SER_CMD_NONSCAN, queue_type);
906 		break;
907 	case WLAN_SER_CANCEL_PDEV_NON_SCAN_CMD:
908 		/* remove all non scan cmds which matches the pdev object */
909 		status = wlan_serialization_cmd_cancel_handler(
910 				ser_obj, NULL, pdev, NULL,
911 				WLAN_SER_CMD_NONSCAN, queue_type);
912 		break;
913 	case WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD:
914 		/* remove all non scan cmds which matches the vdev object */
915 		status = wlan_serialization_cmd_cancel_handler(
916 				ser_obj, NULL, NULL, cmd->vdev,
917 				WLAN_SER_CMD_NONSCAN, queue_type);
918 		break;
919 	case WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE:
920 		/*
921 		 * remove all non scan cmds which matches the vdev
922 		 * and given cmd type
923 		 */
924 		status = wlan_serialization_cmd_cancel_handler(
925 				ser_obj, NULL, NULL, cmd->vdev,
926 				cmd->cmd_type, queue_type);
927 		break;
928 	default:
929 		ser_err("Invalid request");
930 	}
931 
932 error:
933 	ser_exit();
934 	return status;
935 }
936