xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_utils.c (revision a175314c51a4ce5cec2835cc8a8c7dc0c1810915)
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_utils.c
20  * This file defines the utility helper functions for serialization component.
21  */
22 
23 #include "wlan_serialization_utils_i.h"
24 #include "wlan_serialization_main_i.h"
25 #include "wlan_serialization_api.h"
26 #include "wlan_objmgr_vdev_obj.h"
27 #include "wlan_objmgr_pdev_obj.h"
28 #include "qdf_mc_timer.h"
29 #include "wlan_utility.h"
30 
31 QDF_STATUS
32 wlan_serialization_put_back_to_global_list(qdf_list_t *queue,
33 		struct wlan_serialization_pdev_priv_obj *ser_pdev_obj,
34 		struct wlan_serialization_command_list *cmd_list)
35 {
36 	QDF_STATUS status;
37 	uint32_t cmd_id, cmd_type;
38 
39 	if (!queue || !ser_pdev_obj || !cmd_list) {
40 		serialization_err("input parameters are invalid");
41 		return QDF_STATUS_E_FAILURE;
42 	}
43 	/*
44 	 * if the command is already removed in other context,
45 	 * then it will be marked as inactive with the same
46 	 * below code. So, test before proceeding.
47 	 */
48 	if (!qdf_atomic_test_and_clear_bit(CMD_IS_ACTIVE,
49 					   &cmd_list->cmd_in_use)) {
50 		serialization_debug("CMD is not active or being used");
51 		return QDF_STATUS_SUCCESS;
52 	}
53 	status = wlan_serialization_remove_node(queue, &cmd_list->node,
54 						ser_pdev_obj);
55 	if (QDF_STATUS_SUCCESS != status) {
56 		serialization_err("can't remove cmd from queue");
57 		/* assert to catch any leaks */
58 		QDF_ASSERT(0);
59 		return status;
60 	}
61 	cmd_id = cmd_list->cmd.cmd_id;
62 	cmd_type = cmd_list->cmd.cmd_type;
63 	qdf_mem_zero(&cmd_list->cmd, sizeof(struct wlan_serialization_command));
64 	status = wlan_serialization_insert_back(
65 			&ser_pdev_obj->global_cmd_pool_list,
66 			&cmd_list->node, ser_pdev_obj);
67 	qdf_atomic_clear_bit(CMD_MARKED_FOR_DELETE, &cmd_list->cmd_in_use);
68 	if (QDF_STATUS_SUCCESS != status) {
69 		serialization_err("can't put command back to global pool");
70 		QDF_ASSERT(0);
71 	}
72 	serialization_debug("cmd_id-%d, cmd_type-%d", cmd_id, cmd_type);
73 
74 	return status;
75 }
76 
77 struct wlan_objmgr_pdev*
78 wlan_serialization_get_pdev_from_cmd(struct wlan_serialization_command *cmd)
79 {
80 	struct wlan_objmgr_pdev *pdev = NULL;
81 
82 	if (!cmd) {
83 		serialization_err("invalid cmd");
84 		return pdev;
85 	}
86 	if (!cmd->vdev) {
87 		serialization_err("invalid cmd->vdev");
88 		return pdev;
89 	}
90 	pdev = wlan_vdev_get_pdev(cmd->vdev);
91 
92 	return pdev;
93 }
94 
95 QDF_STATUS wlan_serialization_get_cmd_from_queue(qdf_list_t *queue,
96 			qdf_list_node_t **nnode,
97 			struct wlan_serialization_pdev_priv_obj *ser_pdev_obj)
98 {
99 	QDF_STATUS status;
100 	qdf_list_node_t *pnode;
101 
102 	if (!queue || !ser_pdev_obj) {
103 		serialization_err("input parameters are invalid");
104 		return QDF_STATUS_E_FAILURE;
105 	}
106 
107 	pnode = *nnode;
108 	if (!pnode)
109 		status = wlan_serialization_peek_front(queue, nnode,
110 						       ser_pdev_obj);
111 	else
112 		status = wlan_serialization_peek_next(queue, pnode, nnode,
113 						      ser_pdev_obj);
114 
115 	if (status != QDF_STATUS_SUCCESS) {
116 		serialization_err("can't get next node from queue");
117 	}
118 
119 	return status;
120 }
121 
122 /**
123  * wlan_serialization_timer_destroy() - destroys the timer
124  * @ser_timer: pointer to particular timer
125  *
126  * This API destroys the memory allocated by timer and assigns cmd member of
127  * that timer structure to NULL
128  *
129  * Return: QDF_STATUS
130  */
131 static QDF_STATUS wlan_serialization_timer_destroy(
132 		struct wlan_serialization_timer *ser_timer)
133 {
134 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
135 
136 	if (!ser_timer || !ser_timer->cmd) {
137 		serialization_debug("Invalid ser_timer");
138 		return status;
139 	}
140 	status = qdf_mc_timer_destroy(&ser_timer->timer);
141 	if (!QDF_IS_STATUS_SUCCESS(status)) {
142 		serialization_err("Failed to destroy timer for cmd_id[%d]",
143 				ser_timer->cmd->cmd_id);
144 		QDF_ASSERT(0);
145 		return status;
146 	}
147 	ser_timer->cmd = NULL;
148 
149 	return status;
150 }
151 
152 /**
153  * wlan_serialization_generic_timer_callback() - timer callback when timer fire
154  * @arg: argument that timer passes to this callback
155  *
156  * All the timers in serialization module calls this callback when they fire,
157  * and this API in turn calls command specific timeout callback and remove
158  * timed-out command from active queue and move any pending command to active
159  * queue of same cmd_type.
160  *
161  * Return: none
162  */
163 static void wlan_serialization_generic_timer_callback(void *arg)
164 {
165 	struct wlan_serialization_timer *timer = arg;
166 	struct wlan_serialization_command *cmd = timer->cmd;
167 
168 	if (!cmd) {
169 		serialization_err("command not found");
170 		QDF_ASSERT(0);
171 		return;
172 	}
173 
174 	serialization_err("active cmd timeout for cmd_type[%d] vdev[%pK]",
175 			  cmd->cmd_type, cmd->vdev);
176 	if (cmd->cmd_cb)
177 		cmd->cmd_cb(cmd, WLAN_SER_CB_ACTIVE_CMD_TIMEOUT);
178 
179 	if (cmd->cmd_type >= WLAN_SER_CMD_NONSCAN)
180 		QDF_BUG(0);
181 	/*
182 	 * dequeue cmd API will cleanup and destroy the timer. If it fails to
183 	 * dequeue command then we have to destroy the timer. It will also call
184 	 * cmd callback with WLAN_SER_CB_RELEASE_MEM_CMD to free the memory.
185 	 */
186 	if (WLAN_SER_CMD_NOT_FOUND == wlan_serialization_dequeue_cmd(cmd, true))
187 		wlan_serialization_timer_destroy(timer);
188 	if (cmd->cmd_cb)
189 		cmd->cmd_cb(cmd, WLAN_SER_CB_RELEASE_MEM_CMD);
190 }
191 
192 /**
193  * wlan_serialization_stop_timer() - to stop particular timer
194  * @ser_timer: pointer to serialization timer
195  *
196  * This API stops the particular timer
197  *
198  * Return: QDF_STATUS
199  */
200 static QDF_STATUS
201 wlan_serialization_stop_timer(struct wlan_serialization_timer *ser_timer)
202 {
203 	QDF_TIMER_STATE state;
204 	QDF_STATUS status;
205 
206 	state = qdf_mc_timer_get_current_state(&ser_timer->timer);
207 	if (QDF_TIMER_STATE_RUNNING != state &&
208 			QDF_TIMER_STATE_STARTING != state) {
209 		serialization_debug("nothing to stop");
210 		wlan_serialization_timer_destroy(ser_timer);
211 		return QDF_STATUS_SUCCESS;
212 	}
213 	status = qdf_mc_timer_stop(&ser_timer->timer);
214 	if (!QDF_IS_STATUS_SUCCESS(status)) {
215 		serialization_err("Failed to stop timer");
216 		/* to catch the bug */
217 		QDF_ASSERT(0);
218 		return status;
219 	}
220 	wlan_serialization_timer_destroy(ser_timer);
221 	status = QDF_STATUS_SUCCESS;
222 
223 	return status;
224 }
225 
226 QDF_STATUS wlan_serialization_cleanup_all_timers(
227 			struct wlan_serialization_psoc_priv_obj *psoc_ser_obj)
228 {
229 	struct wlan_serialization_timer *ser_timer;
230 	QDF_STATUS status = QDF_STATUS_SUCCESS;
231 	uint32_t i = 0;
232 
233 	if (!psoc_ser_obj) {
234 		serialization_err("Invalid psoc_ser_obj");
235 		return QDF_STATUS_E_FAILURE;
236 	}
237 
238 	for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) {
239 		ser_timer = &psoc_ser_obj->timers[i];
240 		if (!ser_timer->cmd)
241 			continue;
242 		status = wlan_serialization_stop_timer(ser_timer);
243 		if (QDF_STATUS_SUCCESS != status) {
244 			/* lets not break the loop but report error */
245 			serialization_err("some error in stopping timer");
246 		}
247 	}
248 
249 	return status;
250 }
251 
252 QDF_STATUS
253 wlan_serialization_find_and_stop_timer(struct wlan_objmgr_psoc *psoc,
254 				       struct wlan_serialization_command *cmd)
255 {
256 	struct wlan_serialization_psoc_priv_obj *psoc_ser_obj;
257 	struct wlan_serialization_timer *ser_timer;
258 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
259 	int i = 0;
260 
261 	if (!psoc || !cmd) {
262 		serialization_err("invalid param");
263 		return status;
264 	}
265 
266 	if ((cmd->cmd_timeout_duration == 0) &&
267 		(wlan_is_emulation_platform(wlan_psoc_get_nif_phy_version(psoc)
268 	))) {
269 		serialization_err("[SCAN-EMULATION]: Not performing timer functions\n");
270 		return QDF_STATUS_SUCCESS;
271 	}
272 
273 	psoc_ser_obj = wlan_serialization_get_psoc_priv_obj(psoc);
274 	/*
275 	 * Here cmd_id and cmd_type are used to locate the timer being
276 	 * associated with command. For scan command, cmd_id is expected to
277 	 * be unique and For non-scan command, there should be only one active
278 	 * command per pdev
279 	 */
280 	for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) {
281 		ser_timer = &psoc_ser_obj->timers[i];
282 		if (!(ser_timer->cmd) ||
283 				(ser_timer->cmd->cmd_id != cmd->cmd_id) ||
284 				(ser_timer->cmd->cmd_type != cmd->cmd_type) ||
285 				(ser_timer->cmd->vdev != cmd->vdev))
286 			continue;
287 		status = wlan_serialization_stop_timer(ser_timer);
288 		if (QDF_STATUS_SUCCESS != status) {
289 			serialization_err("Failed to stop timer for cmd_id[%d]",
290 					cmd->cmd_id);
291 		}
292 		break;
293 	}
294 
295 	if (QDF_STATUS_SUCCESS != status) {
296 		serialization_err("can't find timer for cmd_type[%d]",
297 				cmd->cmd_type);
298 	}
299 	return status;
300 }
301 
302 QDF_STATUS
303 wlan_serialization_find_and_start_timer(struct wlan_objmgr_psoc *psoc,
304 					struct wlan_serialization_command *cmd)
305 {
306 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
307 	struct wlan_serialization_psoc_priv_obj *psoc_ser_obj;
308 	struct wlan_serialization_timer *ser_timer;
309 	int i = 0;
310 
311 	if (!psoc || !cmd) {
312 		serialization_err("invalid param");
313 		return status;
314 	}
315 
316 	if ((cmd->cmd_timeout_duration == 0) &&
317 		(wlan_is_emulation_platform(wlan_psoc_get_nif_phy_version(psoc)
318 	))) {
319 		serialization_err("[SCAN-EMULATION]: Not performing timer functions\n");
320 		return QDF_STATUS_SUCCESS;
321 	}
322 
323 
324 	psoc_ser_obj = wlan_serialization_get_psoc_priv_obj(psoc);
325 	for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) {
326 		/* Keep trying timer */
327 		ser_timer = &psoc_ser_obj->timers[i];
328 		if (ser_timer->cmd)
329 			continue;
330 		/* Remember timer is pointing to command */
331 		ser_timer->cmd = cmd;
332 		if (!QDF_IS_STATUS_SUCCESS(qdf_mc_timer_init(&ser_timer->timer,
333 				QDF_TIMER_TYPE_SW,
334 				wlan_serialization_generic_timer_callback,
335 				ser_timer))) {
336 			serialization_err("Failed to init timer cmdid [%d]",
337 					cmd->cmd_id);
338 			QDF_ASSERT(0);
339 			continue;
340 		}
341 		if (!QDF_IS_STATUS_SUCCESS(qdf_mc_timer_start(&ser_timer->timer,
342 						cmd->cmd_timeout_duration))) {
343 			serialization_err("Failed to start timer cmdid [%d]",
344 					cmd->cmd_id);
345 			wlan_serialization_timer_destroy(ser_timer);
346 			QDF_ASSERT(0);
347 			continue;
348 		}
349 		status = QDF_STATUS_SUCCESS;
350 		break;
351 	}
352 
353 	return status;
354 }
355 
356 /**
357  * wlan_serialization_active_scan_cmd_count_handler() - count active scan cmds
358  * @psoc: pointer to soc strucutre
359  * @obj : pointer to pdev object
360  * @arg: pointer to argument
361  *
362  * This API will be called while iterating each pdev object and it will count
363  * number of scan commands present in that pdev object's active queue. count
364  * will be updated in *arg
365  *
366  * Return: none
367  */
368 static void
369 wlan_serialization_active_scan_cmd_count_handler(struct wlan_objmgr_psoc *psoc,
370 						 void *obj, void *arg)
371 {
372 	struct wlan_objmgr_pdev *pdev = obj;
373 	struct wlan_serialization_pdev_priv_obj *ser_pdev_obj;
374 	uint32_t *count = arg;
375 
376 	if (!pdev) {
377 		serialization_err("invalid pdev");
378 		return;
379 	}
380 
381 	ser_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(
382 			pdev, WLAN_UMAC_COMP_SERIALIZATION);
383 	*count += wlan_serialization_list_size(&ser_pdev_obj->active_scan_list,
384 					       ser_pdev_obj);
385 }
386 
387 /**
388  * wlan_serialization_is_active_scan_cmd_allowed() - find if scan cmd allowed
389  * @pdev: pointer to pdev object
390  *
391  * This API will be called to find out if active scan cmd is allowed. It has
392  * to iterate through all pdev to find out total number of active scan cmds.
393  * If total number of active scan cmds reach to allowed threshold then don't
394  * allow more scan cmd.
395  *
396  * Return: true or false
397  */
398 static bool
399 wlan_serialization_is_active_scan_cmd_allowed(struct wlan_objmgr_pdev *pdev)
400 {
401 	uint32_t count = 0;
402 	struct wlan_objmgr_psoc *psoc;
403 
404 	if (!pdev) {
405 		serialization_err("invalid pdev");
406 		return false;
407 	}
408 
409 	psoc = wlan_pdev_get_psoc(pdev);
410 
411 	if (!psoc) {
412 		serialization_err("invalid psoc");
413 		return false;
414 	}
415 
416 	wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
417 			wlan_serialization_active_scan_cmd_count_handler,
418 			&count, 1, WLAN_SERIALIZATION_ID);
419 	if (count < ucfg_scan_get_max_active_scans(psoc)) {
420 		serialization_debug("count is [%d]", count);
421 		return true;
422 	}
423 
424 	return false;
425 }
426 
427 /**
428  * wlan_serialization_is_active_nonscan_cmd_allowed() - find if cmd allowed
429  * @pdev: pointer to pdev object
430  *
431  * This API will be called to find out if non scan cmd is allowed.
432  *
433  * Return: true or false
434  */
435 static bool
436 wlan_serialization_is_active_nonscan_cmd_allowed(struct wlan_objmgr_pdev *pdev)
437 {
438 	struct wlan_serialization_pdev_priv_obj *ser_pdev_obj;
439 
440 	if (!pdev) {
441 		serialization_err("invalid pdev");
442 		return false;
443 	}
444 
445 	ser_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(
446 			pdev, WLAN_UMAC_COMP_SERIALIZATION);
447 
448 	if (!ser_pdev_obj) {
449 		serialization_err("invalid ser_pdev_obj");
450 		return false;
451 	}
452 
453 	if (wlan_serialization_list_empty(&ser_pdev_obj->active_list,
454 					  ser_pdev_obj))
455 		return true;
456 
457 	return false;
458 }
459 
460 bool
461 wlan_serialization_is_active_cmd_allowed(struct wlan_serialization_command *cmd)
462 {
463 	struct wlan_objmgr_pdev *pdev;
464 
465 	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
466 	if (!pdev) {
467 		serialization_err("NULL pdev");
468 		return false;
469 	}
470 
471 	if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN)
472 		return wlan_serialization_is_active_scan_cmd_allowed(pdev);
473 	else
474 		return wlan_serialization_is_active_nonscan_cmd_allowed(pdev);
475 }
476 
477 QDF_STATUS wlan_serialization_validate_cmdtype(
478 		 enum wlan_serialization_cmd_type cmd_type)
479 {
480 	serialization_debug("validate cmd_type:%d", cmd_type);
481 
482 	if (cmd_type < 0 || cmd_type >= WLAN_SER_CMD_MAX) {
483 		serialization_err("Invalid cmd or comp passed");
484 		return QDF_STATUS_E_INVAL;
485 	}
486 
487 	return QDF_STATUS_SUCCESS;
488 }
489 
490 QDF_STATUS wlan_serialization_validate_cmd(
491 		 enum wlan_umac_comp_id comp_id,
492 		 enum wlan_serialization_cmd_type cmd_type)
493 {
494 	serialization_debug("validate cmd_type:%d, comp_id:%d",
495 			cmd_type, comp_id);
496 	if (cmd_type < 0 || comp_id < 0 ||
497 			cmd_type >= WLAN_SER_CMD_MAX ||
498 			comp_id >= WLAN_UMAC_COMP_ID_MAX) {
499 		serialization_err("Invalid cmd or comp passed");
500 		return QDF_STATUS_E_INVAL;
501 	}
502 
503 	return QDF_STATUS_SUCCESS;
504 }
505 
506 static void wlan_serialization_release_list_cmds(
507 		struct wlan_serialization_pdev_priv_obj *ser_pdev_obj,
508 		qdf_list_t *list)
509 {
510 	qdf_list_node_t *node = NULL;
511 
512 	while (!wlan_serialization_list_empty(list, ser_pdev_obj)) {
513 		wlan_serialization_remove_front(list, &node, ser_pdev_obj);
514 		wlan_serialization_insert_back(
515 				&ser_pdev_obj->global_cmd_pool_list,
516 				node, ser_pdev_obj);
517 	}
518 
519 	return;
520 }
521 
522 void wlan_serialization_destroy_list(
523 		struct wlan_serialization_pdev_priv_obj *ser_pdev_obj,
524 		qdf_list_t *list)
525 {
526 	wlan_serialization_release_list_cmds(ser_pdev_obj, list);
527 	qdf_list_destroy(list);
528 }
529 
530 struct wlan_serialization_psoc_priv_obj *wlan_serialization_get_psoc_priv_obj(
531 		struct wlan_objmgr_psoc *psoc)
532 {
533 	struct wlan_serialization_psoc_priv_obj *ser_soc_obj;
534 	ser_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
535 					WLAN_UMAC_COMP_SERIALIZATION);
536 
537 	return ser_soc_obj;
538 }
539 
540 struct wlan_serialization_pdev_priv_obj *wlan_serialization_get_pdev_priv_obj(
541 		struct wlan_objmgr_pdev *pdev)
542 {
543 	struct wlan_serialization_pdev_priv_obj *obj;
544 	obj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
545 					WLAN_UMAC_COMP_SERIALIZATION);
546 
547 	return obj;
548 }
549 
550 struct wlan_serialization_psoc_priv_obj *
551 wlan_serialization_get_psoc_obj(struct wlan_serialization_command *cmd)
552 {
553 	struct wlan_serialization_psoc_priv_obj *ser_soc_obj = NULL;
554 	struct wlan_objmgr_psoc *psoc;
555 
556 	if (!cmd->vdev)
557 		return ser_soc_obj;
558 
559 	psoc = wlan_vdev_get_psoc(cmd->vdev);
560 	ser_soc_obj = wlan_serialization_get_psoc_priv_obj(psoc);
561 
562 	return ser_soc_obj;
563 }
564 
565 bool wlan_serialization_is_cmd_in_vdev_list(struct wlan_objmgr_vdev *vdev,
566 					    qdf_list_t *queue)
567 {
568 	uint32_t queuelen;
569 	qdf_list_node_t *nnode = NULL;
570 	struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev);
571 	struct wlan_serialization_pdev_priv_obj *ser_pdev_obj =
572 		wlan_serialization_get_pdev_priv_obj(pdev);
573 	QDF_STATUS status;
574 
575 	queuelen = wlan_serialization_list_size(queue, ser_pdev_obj);
576 	if (!queuelen) {
577 		serialization_debug("queue empty");
578 		return false;
579 	}
580 
581 	while (queuelen--) {
582 		status = wlan_serialization_get_cmd_from_queue(queue, &nnode,
583 							       ser_pdev_obj);
584 		if (status != QDF_STATUS_SUCCESS)
585 			break;
586 		if (wlan_serialization_match_cmd_vdev(nnode, vdev))
587 			return true;
588 	}
589 
590 	return false;
591 }
592 
593 bool wlan_serialization_is_cmd_in_pdev_list(
594 			struct wlan_objmgr_pdev *pdev,
595 			qdf_list_t *queue)
596 {
597 	uint32_t queuelen;
598 	qdf_list_node_t *nnode = NULL;
599 	struct wlan_serialization_pdev_priv_obj *ser_pdev_obj =
600 		wlan_serialization_get_pdev_priv_obj(pdev);
601 	QDF_STATUS status;
602 
603 	queuelen = wlan_serialization_list_size(queue, ser_pdev_obj);
604 	if (!queuelen) {
605 		serialization_debug("queue empty");
606 		return false;
607 	}
608 
609 	while (queuelen--) {
610 		status = wlan_serialization_get_cmd_from_queue(queue, &nnode,
611 							       ser_pdev_obj);
612 		if (status != QDF_STATUS_SUCCESS)
613 			break;
614 		if (wlan_serialization_match_cmd_pdev(nnode, pdev))
615 			return true;
616 	}
617 
618 	return false;
619 }
620 
621 enum wlan_serialization_cmd_status
622 wlan_serialization_is_cmd_in_active_pending(bool cmd_in_active,
623 					    bool cmd_in_pending)
624 {
625 	if (cmd_in_active && cmd_in_pending)
626 		return WLAN_SER_CMDS_IN_ALL_LISTS;
627 	else if (cmd_in_active)
628 		return WLAN_SER_CMD_IN_ACTIVE_LIST;
629 	else if (cmd_in_pending)
630 		return WLAN_SER_CMD_IN_PENDING_LIST;
631 	else
632 		return WLAN_SER_CMD_NOT_FOUND;
633 }
634 
635 static bool wlan_serialization_is_cmd_present_in_given_queue(qdf_list_t *queue,
636 			struct wlan_serialization_command *cmd,
637 			struct wlan_serialization_pdev_priv_obj *ser_pdev_obj)
638 {
639 	uint32_t qsize;
640 	QDF_STATUS status;
641 	struct wlan_serialization_command_list *cmd_list = NULL;
642 	qdf_list_node_t *nnode = NULL, *pnode = NULL;
643 	bool found = false;
644 
645 	qsize = wlan_serialization_list_size(queue, ser_pdev_obj);
646 	while (qsize--) {
647 		if (!cmd_list)
648 			status = wlan_serialization_peek_front(queue, &nnode,
649 							       ser_pdev_obj);
650 		else
651 			status = wlan_serialization_peek_next(queue, pnode,
652 							      &nnode,
653 							      ser_pdev_obj);
654 
655 		if (status != QDF_STATUS_SUCCESS)
656 			break;
657 
658 		pnode = nnode;
659 		cmd_list = qdf_container_of(nnode,
660 				struct wlan_serialization_command_list, node);
661 		if (wlan_serialization_match_cmd_id_type(nnode, cmd,
662 							 ser_pdev_obj) &&
663 			wlan_serialization_match_cmd_vdev(nnode, cmd->vdev)) {
664 			found = true;
665 			break;
666 		}
667 		nnode = NULL;
668 	}
669 
670 	return found;
671 }
672 
673 bool wlan_serialization_is_cmd_present_queue(
674 			struct wlan_serialization_command *cmd,
675 			uint8_t is_active_queue)
676 {
677 	qdf_list_t *queue;
678 	struct wlan_objmgr_pdev *pdev;
679 	struct wlan_serialization_pdev_priv_obj *ser_pdev_obj;
680 
681 	if (!cmd) {
682 		serialization_err("invalid params");
683 		return false;
684 	}
685 	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
686 	if (!pdev) {
687 		serialization_err("invalid pdev");
688 		return false;
689 	}
690 	ser_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
691 					WLAN_UMAC_COMP_SERIALIZATION);
692 	if (!ser_pdev_obj) {
693 		serialization_err("invalid ser_pdev_obj");
694 		return false;
695 	}
696 	if (!is_active_queue) {
697 		if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN)
698 			queue = &ser_pdev_obj->pending_scan_list;
699 		else
700 			queue = &ser_pdev_obj->pending_list;
701 	} else {
702 		if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN)
703 			queue = &ser_pdev_obj->active_scan_list;
704 		else
705 			queue = &ser_pdev_obj->active_list;
706 	}
707 
708 	return wlan_serialization_is_cmd_present_in_given_queue(queue, cmd,
709 								ser_pdev_obj);
710 }
711 
712 bool wlan_serialization_list_empty(
713 			qdf_list_t *queue,
714 			struct wlan_serialization_pdev_priv_obj *ser_pdev_obj)
715 {
716 	bool is_empty;
717 
718 	wlan_serialization_acquire_lock(ser_pdev_obj);
719 	if (qdf_list_empty(queue))
720 		is_empty = true;
721 	else
722 		is_empty = false;
723 	wlan_serialization_release_lock(ser_pdev_obj);
724 
725 	return is_empty;
726 }
727 
728 uint32_t wlan_serialization_list_size(
729 			qdf_list_t *queue,
730 			struct wlan_serialization_pdev_priv_obj *ser_pdev_obj)
731 {
732 	uint32_t size;
733 
734 	wlan_serialization_acquire_lock(ser_pdev_obj);
735 	size = qdf_list_size(queue);
736 	wlan_serialization_release_lock(ser_pdev_obj);
737 
738 	return size;
739 }
740 
741 QDF_STATUS wlan_serialization_remove_front(
742 			qdf_list_t *list,
743 			qdf_list_node_t **node,
744 			struct wlan_serialization_pdev_priv_obj *ser_pdev_obj)
745 {
746 	QDF_STATUS status;
747 
748 	wlan_serialization_acquire_lock(ser_pdev_obj);
749 	status = qdf_list_remove_front(list, node);
750 	wlan_serialization_release_lock(ser_pdev_obj);
751 
752 	return status;
753 }
754 
755 QDF_STATUS wlan_serialization_remove_node(
756 			qdf_list_t *list,
757 			qdf_list_node_t *node,
758 			struct wlan_serialization_pdev_priv_obj *ser_pdev_obj)
759 {
760 	QDF_STATUS status;
761 
762 	wlan_serialization_acquire_lock(ser_pdev_obj);
763 	status = qdf_list_remove_node(list, node);
764 	wlan_serialization_release_lock(ser_pdev_obj);
765 
766 	return status;
767 }
768 
769 QDF_STATUS wlan_serialization_insert_front(
770 			qdf_list_t *list,
771 			qdf_list_node_t *node,
772 			struct wlan_serialization_pdev_priv_obj *ser_pdev_obj)
773 {
774 	QDF_STATUS status;
775 
776 	wlan_serialization_acquire_lock(ser_pdev_obj);
777 	status = qdf_list_insert_front(list, node);
778 	wlan_serialization_release_lock(ser_pdev_obj);
779 
780 	return status;
781 }
782 
783 QDF_STATUS wlan_serialization_insert_back(
784 			qdf_list_t *list,
785 			qdf_list_node_t *node,
786 			struct wlan_serialization_pdev_priv_obj *ser_pdev_obj)
787 {
788 	QDF_STATUS status;
789 
790 	wlan_serialization_acquire_lock(ser_pdev_obj);
791 	status = qdf_list_insert_back(list, node);
792 	wlan_serialization_release_lock(ser_pdev_obj);
793 
794 	return status;
795 }
796 
797 QDF_STATUS wlan_serialization_peek_front(
798 			qdf_list_t *list,
799 			qdf_list_node_t **node,
800 			struct wlan_serialization_pdev_priv_obj *ser_pdev_obj)
801 {
802 	QDF_STATUS status;
803 
804 	wlan_serialization_acquire_lock(ser_pdev_obj);
805 	status = qdf_list_peek_front(list, node);
806 	wlan_serialization_release_lock(ser_pdev_obj);
807 
808 	return status;
809 }
810 
811 QDF_STATUS wlan_serialization_peek_next(
812 			qdf_list_t *list,
813 			qdf_list_node_t *node1, qdf_list_node_t **node2,
814 			struct wlan_serialization_pdev_priv_obj *ser_pdev_obj)
815 {
816 	QDF_STATUS status;
817 
818 	wlan_serialization_acquire_lock(ser_pdev_obj);
819 	status = qdf_list_peek_next(list, node1, node2);
820 	wlan_serialization_release_lock(ser_pdev_obj);
821 
822 	return status;
823 }
824 
825 bool wlan_serialization_match_cmd_scan_id(
826 			qdf_list_node_t *nnode,
827 			struct wlan_serialization_command **cmd,
828 			uint16_t scan_id, struct wlan_objmgr_vdev *vdev,
829 			struct wlan_serialization_pdev_priv_obj *ser_pdev_obj)
830 {
831 	struct wlan_serialization_command_list *cmd_list = NULL;
832 	bool match_found = false;
833 
834 	wlan_serialization_acquire_lock(ser_pdev_obj);
835 	cmd_list = qdf_container_of(nnode,
836 				    struct wlan_serialization_command_list,
837 				    node);
838 	if ((cmd_list->cmd.cmd_id == scan_id) &&
839 	    (cmd_list->cmd.vdev == vdev)) {
840 		*cmd = &cmd_list->cmd;
841 		match_found = true;
842 	};
843 	wlan_serialization_release_lock(ser_pdev_obj);
844 
845 	return match_found;
846 }
847 
848 bool wlan_serialization_match_cmd_id_type(
849 			qdf_list_node_t *nnode,
850 			struct wlan_serialization_command *cmd,
851 			struct wlan_serialization_pdev_priv_obj *ser_pdev_obj)
852 {
853 	struct wlan_serialization_command_list *cmd_list = NULL;
854 	bool match_found = true;
855 
856 	if (!cmd)
857 		return false;
858 	wlan_serialization_acquire_lock(ser_pdev_obj);
859 	cmd_list = qdf_container_of(nnode,
860 				    struct wlan_serialization_command_list,
861 				    node);
862 	if ((cmd_list->cmd.cmd_id != cmd->cmd_id) ||
863 	    (cmd_list->cmd.cmd_type != cmd->cmd_type)) {
864 		match_found = false;
865 	};
866 	wlan_serialization_release_lock(ser_pdev_obj);
867 
868 	return match_found;
869 }
870 
871 bool wlan_serialization_match_cmd_vdev(qdf_list_node_t *nnode,
872 				       struct wlan_objmgr_vdev *vdev)
873 {
874 	struct wlan_serialization_command_list *cmd_list = NULL;
875 	bool match_found = false;
876 	struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev);
877 	struct wlan_serialization_pdev_priv_obj *ser_pdev_obj =
878 		wlan_serialization_get_pdev_priv_obj(pdev);
879 
880 	wlan_serialization_acquire_lock(ser_pdev_obj);
881 	cmd_list = qdf_container_of(nnode,
882 				    struct wlan_serialization_command_list,
883 				    node);
884 	if (cmd_list->cmd.vdev == vdev)
885 		match_found = true;
886 	wlan_serialization_release_lock(ser_pdev_obj);
887 
888 	return match_found;
889 }
890 
891 bool wlan_serialization_match_cmd_pdev(qdf_list_node_t *nnode,
892 				       struct wlan_objmgr_pdev *pdev)
893 {
894 	struct wlan_serialization_command_list *cmd_list = NULL;
895 	bool match_found = false;
896 	struct wlan_serialization_pdev_priv_obj *ser_pdev_obj =
897 		wlan_serialization_get_pdev_priv_obj(pdev);
898 	struct wlan_objmgr_pdev *node_pdev = NULL;
899 
900 	wlan_serialization_acquire_lock(ser_pdev_obj);
901 	cmd_list = qdf_container_of(nnode,
902 				    struct wlan_serialization_command_list,
903 				    node);
904 	node_pdev = wlan_vdev_get_pdev(cmd_list->cmd.vdev);
905 	if (node_pdev == pdev)
906 		match_found = true;
907 	wlan_serialization_release_lock(ser_pdev_obj);
908 
909 	return match_found;
910 }
911 
912 #ifdef WLAN_CMD_SERIALIZATION_LOCKING
913 QDF_STATUS
914 wlan_serialization_acquire_lock(struct wlan_serialization_pdev_priv_obj *obj)
915 {
916 	if (!obj) {
917 		serialization_err("invalid object");
918 		return QDF_STATUS_E_FAILURE;
919 	}
920 	qdf_spin_lock_bh(&obj->pdev_ser_list_lock);
921 
922 	return QDF_STATUS_SUCCESS;
923 }
924 
925 QDF_STATUS
926 wlan_serialization_release_lock(struct wlan_serialization_pdev_priv_obj *obj)
927 {
928 	if (!obj) {
929 		serialization_err("invalid object");
930 		return QDF_STATUS_E_FAILURE;
931 	}
932 	qdf_spin_unlock_bh(&obj->pdev_ser_list_lock);
933 
934 	return QDF_STATUS_SUCCESS;
935 }
936 
937 QDF_STATUS
938 wlan_serialization_create_lock(struct wlan_serialization_pdev_priv_obj *obj)
939 {
940 	if (!obj) {
941 		serialization_err("invalid object");
942 		return QDF_STATUS_E_FAILURE;
943 	}
944 	qdf_spinlock_create(&obj->pdev_ser_list_lock);
945 
946 	return QDF_STATUS_SUCCESS;
947 }
948 
949 QDF_STATUS
950 wlan_serialization_destroy_lock(struct wlan_serialization_pdev_priv_obj *obj)
951 {
952 	if (!obj) {
953 		serialization_err("invalid object");
954 		return QDF_STATUS_E_FAILURE;
955 	}
956 	qdf_spinlock_destroy(&obj->pdev_ser_list_lock);
957 
958 	return QDF_STATUS_SUCCESS;
959 }
960 #else
961 QDF_STATUS
962 wlan_serialization_acquire_lock(struct wlan_serialization_pdev_priv_obj *obj)
963 {
964 	return QDF_STATUS_SUCCESS;
965 }
966 
967 QDF_STATUS
968 wlan_serialization_release_lock(struct wlan_serialization_pdev_priv_obj *obj)
969 {
970 	return QDF_STATUS_SUCCESS;
971 }
972 
973 QDF_STATUS
974 wlan_serialization_create_lock(struct wlan_serialization_pdev_priv_obj *obj)
975 {
976 	return QDF_STATUS_SUCCESS;
977 }
978 
979 QDF_STATUS
980 wlan_serialization_destroy_lock(struct wlan_serialization_pdev_priv_obj *obj)
981 {
982 	return QDF_STATUS_SUCCESS;
983 }
984 #endif
985