xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_api.c (revision 503663c6daafffe652fa360bde17243568cd6d2a)
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 /**
20  * DOC: wlan_serialization_api.c
21  * This file provides an interface for the external components
22  * to utilize the services provided by the serialization
23  * component.
24  */
25 
26 #include <wlan_objmgr_psoc_obj.h>
27 #include <wlan_objmgr_pdev_obj.h>
28 #include <wlan_objmgr_vdev_obj.h>
29 #include "wlan_serialization_main_i.h"
30 #include "wlan_serialization_utils_i.h"
31 #include "wlan_serialization_queue_i.h"
32 #include "wlan_serialization_scan_i.h"
33 #include "wlan_serialization_internal_i.h"
34 
35 bool wlan_serialization_is_cmd_present_in_pending_queue(
36 		struct wlan_objmgr_psoc *psoc,
37 		struct wlan_serialization_command *cmd)
38 {
39 	bool status = false;
40 
41 	if (!cmd) {
42 		ser_err("invalid cmd");
43 		goto error;
44 	}
45 
46 	status = wlan_serialization_is_cmd_present_queue(cmd, false);
47 
48 error:
49 	return status;
50 }
51 
52 bool wlan_serialization_is_cmd_present_in_active_queue(
53 		struct wlan_objmgr_psoc *psoc,
54 		struct wlan_serialization_command *cmd)
55 {
56 	bool status;
57 
58 	if (!cmd) {
59 		ser_err("invalid cmd");
60 		status = false;
61 		goto error;
62 	}
63 
64 	status = wlan_serialization_is_cmd_present_queue(cmd, true);
65 
66 	ser_debug("Cmd type:%d id:%d present: %d",
67 		  cmd->cmd_type, cmd->cmd_id, status);
68 
69 error:
70 	return status;
71 }
72 
73 QDF_STATUS
74 wlan_serialization_register_apply_rules_cb(
75 		struct wlan_objmgr_psoc *psoc,
76 		enum wlan_serialization_cmd_type cmd_type,
77 		wlan_serialization_apply_rules_cb cb)
78 {
79 	struct wlan_ser_psoc_obj *ser_soc_obj;
80 	QDF_STATUS status;
81 
82 	status = wlan_serialization_validate_cmdtype(cmd_type);
83 	if (QDF_IS_STATUS_ERROR(status)) {
84 		ser_err("invalid cmd_type %d", cmd_type);
85 		goto error;
86 	}
87 
88 	ser_soc_obj = wlan_serialization_get_psoc_obj(psoc);
89 	if (!ser_soc_obj) {
90 		ser_err("invalid ser_soc_obj");
91 		status = QDF_STATUS_E_FAILURE;
92 		goto error;
93 	}
94 
95 	ser_soc_obj->apply_rules_cb[cmd_type] = cb;
96 	status = QDF_STATUS_SUCCESS;
97 
98 error:
99 	return status;
100 }
101 
102 QDF_STATUS
103 wlan_serialization_deregister_apply_rules_cb(
104 		struct wlan_objmgr_psoc *psoc,
105 		enum wlan_serialization_cmd_type cmd_type)
106 {
107 	struct wlan_ser_psoc_obj *ser_soc_obj;
108 	QDF_STATUS status;
109 
110 	status = wlan_serialization_validate_cmdtype(cmd_type);
111 	if (QDF_IS_STATUS_ERROR(status)) {
112 		ser_err("invalid cmd_type %d", cmd_type);
113 		goto error;
114 	}
115 	ser_soc_obj = wlan_serialization_get_psoc_obj(psoc);
116 	if (!ser_soc_obj) {
117 		ser_err("invalid ser_soc_obj");
118 		status = QDF_STATUS_E_FAILURE;
119 		goto error;
120 	}
121 	ser_soc_obj->apply_rules_cb[cmd_type] = NULL;
122 	status = QDF_STATUS_SUCCESS;
123 
124 error:
125 	return status;
126 }
127 
128 QDF_STATUS
129 wlan_serialization_register_comp_info_cb(
130 		struct wlan_objmgr_psoc *psoc,
131 		enum wlan_umac_comp_id comp_id,
132 		enum wlan_serialization_cmd_type cmd_type,
133 		wlan_serialization_comp_info_cb cb)
134 {
135 	struct wlan_ser_psoc_obj *ser_soc_obj;
136 	QDF_STATUS status;
137 
138 	status = wlan_serialization_validate_cmd(comp_id, cmd_type);
139 	if (QDF_IS_STATUS_ERROR(status)) {
140 		ser_err("invalid comp_id %d or cmd_type %d",
141 			comp_id, cmd_type);
142 		goto error;
143 	}
144 	ser_soc_obj = wlan_serialization_get_psoc_obj(psoc);
145 	if (!ser_soc_obj) {
146 		ser_err("invalid ser_soc_obj");
147 		status = QDF_STATUS_E_FAILURE;
148 		goto error;
149 	}
150 	ser_soc_obj->comp_info_cb[cmd_type][comp_id] = cb;
151 	status = QDF_STATUS_SUCCESS;
152 
153 error:
154 	return status;
155 }
156 
157 QDF_STATUS
158 wlan_serialization_deregister_comp_info_cb(struct wlan_objmgr_psoc *psoc,
159 					   enum wlan_umac_comp_id comp_id,
160 		enum wlan_serialization_cmd_type cmd_type)
161 {
162 	struct wlan_ser_psoc_obj *ser_soc_obj;
163 	QDF_STATUS status;
164 
165 	status = wlan_serialization_validate_cmd(comp_id, cmd_type);
166 	if (QDF_IS_STATUS_ERROR(status)) {
167 		ser_err("invalid comp_id %d or cmd_type %d",
168 			comp_id, cmd_type);
169 		goto error;
170 	}
171 	ser_soc_obj = wlan_serialization_get_psoc_obj(psoc);
172 	if (!ser_soc_obj) {
173 		ser_err("invalid ser_soc_obj");
174 		status = QDF_STATUS_E_FAILURE;
175 		goto error;
176 	}
177 	ser_soc_obj->comp_info_cb[cmd_type][comp_id] = NULL;
178 	status = QDF_STATUS_SUCCESS;
179 
180 error:
181 	return status;
182 }
183 
184 enum wlan_serialization_cmd_status
185 wlan_serialization_non_scan_cmd_status(
186 		struct wlan_objmgr_pdev *pdev,
187 		enum wlan_serialization_cmd_type cmd_type)
188 {
189 	bool cmd_in_active = 0;
190 	bool cmd_in_pending = 0;
191 	struct wlan_ser_pdev_obj *ser_pdev_obj =
192 		wlan_serialization_get_pdev_obj(pdev);
193 	enum wlan_serialization_cmd_status cmd_status = WLAN_SER_CMD_NOT_FOUND;
194 	struct wlan_serialization_pdev_queue *pdev_q;
195 	qdf_list_node_t *node = NULL;
196 	qdf_list_t *queue = NULL;
197 
198 	ser_enter();
199 
200 	pdev_q = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN];
201 
202 	/* Look in the pdev non scan active queue */
203 	queue = &pdev_q->active_list;
204 
205 	wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock);
206 
207 	node = wlan_serialization_find_cmd(
208 			queue, WLAN_SER_MATCH_CMD_TYPE,
209 			NULL, cmd_type, NULL, NULL,  WLAN_SER_PDEV_NODE);
210 
211 	if (node)
212 		cmd_in_active = true;
213 
214 	node = NULL;
215 
216 	/* Look in the pdev non scan pending queue */
217 	queue = &pdev_q->pending_list;
218 
219 	node = wlan_serialization_find_cmd(
220 			queue, WLAN_SER_MATCH_CMD_TYPE,
221 			NULL, cmd_type, NULL, NULL,  WLAN_SER_PDEV_NODE);
222 
223 	if (node)
224 		cmd_in_pending = true;
225 
226 	cmd_status = wlan_serialization_is_cmd_in_active_pending(
227 			cmd_in_active, cmd_in_pending);
228 
229 	wlan_serialization_release_lock(&pdev_q->pdev_queue_lock);
230 
231 	ser_exit();
232 	return cmd_status;
233 }
234 
235 enum wlan_serialization_cmd_status
236 wlan_serialization_cancel_request(
237 		struct wlan_serialization_queued_cmd_info *req)
238 {
239 	QDF_STATUS status;
240 	enum wlan_serialization_cmd_status cmd_status;
241 
242 	struct wlan_serialization_command cmd;
243 	struct wlan_objmgr_pdev *pdev;
244 	struct wlan_ser_pdev_obj *ser_pdev_obj;
245 	struct wlan_serialization_pdev_queue *pdev_queue;
246 
247 	ser_enter();
248 
249 	if (!req) {
250 		ser_err("given request is empty");
251 		cmd_status = WLAN_SER_CMD_NOT_FOUND;
252 		goto error;
253 	}
254 
255 	status = wlan_serialization_validate_cmd(req->requestor, req->cmd_type);
256 	if (QDF_IS_STATUS_ERROR(status)) {
257 		ser_err("req is not valid");
258 		cmd_status = WLAN_SER_CMD_NOT_FOUND;
259 		goto error;
260 	}
261 
262 	cmd.cmd_type = req->cmd_type;
263 	cmd.cmd_id = req->cmd_id;
264 	cmd.source = req->requestor;
265 	cmd.vdev = req->vdev;
266 
267 	pdev = wlan_serialization_get_pdev_from_cmd(&cmd);
268 	if (!pdev) {
269 		ser_err("pdev is invalid");
270 		cmd_status = WLAN_SER_CMD_NOT_FOUND;
271 		goto error;
272 	}
273 
274 	ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev);
275 
276 	pdev_queue = wlan_serialization_get_pdev_queue_obj(ser_pdev_obj,
277 							   cmd.cmd_type);
278 
279 	if (!pdev_queue) {
280 		ser_err("pdev_queue is invalid");
281 		cmd_status = WLAN_SER_CMD_NOT_FOUND;
282 		goto error;
283 	}
284 
285 	cmd_status = wlan_serialization_find_and_cancel_cmd(
286 			&cmd, req->req_type, req->queue_type);
287 
288 error:
289 	ser_exit();
290 	return cmd_status;
291 }
292 
293 void wlan_serialization_remove_cmd(
294 		struct wlan_serialization_queued_cmd_info *cmd_info)
295 {
296 	QDF_STATUS status;
297 	enum wlan_serialization_cmd_status ser_status;
298 	struct wlan_serialization_command cmd = {0};
299 
300 	ser_enter();
301 
302 	if (!cmd_info) {
303 		ser_err("given request is empty");
304 		QDF_ASSERT(0);
305 		return;
306 	}
307 	status = wlan_serialization_validate_cmd(cmd_info->requestor,
308 						 cmd_info->cmd_type);
309 	if (QDF_IS_STATUS_ERROR(status)) {
310 		ser_err("cmd is not valid");
311 		QDF_ASSERT(0);
312 		goto error;
313 	}
314 
315 	cmd.cmd_type = cmd_info->cmd_type;
316 	cmd.cmd_id = cmd_info->cmd_id;
317 	cmd.source = cmd_info->requestor;
318 	cmd.vdev = cmd_info->vdev;
319 
320 	ser_status = wlan_serialization_dequeue_cmd(
321 			&cmd, SER_REMOVE, true);
322 
323 	if (ser_status != WLAN_SER_CMD_IN_ACTIVE_LIST) {
324 		if (ser_status != WLAN_SER_CMD_MARKED_FOR_ACTIVATION)
325 		ser_debug("Can't dequeue requested cmd_id[%d] type[%d]",
326 			  cmd.cmd_id, cmd.cmd_type);
327 	}
328 
329 error:
330 	ser_exit();
331 }
332 
333 enum wlan_serialization_status
334 wlan_serialization_request(struct wlan_serialization_command *cmd)
335 {
336 	QDF_STATUS status;
337 	enum wlan_serialization_status serialization_status;
338 	uint8_t comp_id;
339 	struct wlan_ser_psoc_obj *ser_soc_obj;
340 	union wlan_serialization_rules_info info;
341 	struct wlan_objmgr_psoc *psoc;
342 
343 	ser_enter();
344 
345 	serialization_status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
346 
347 	if (!cmd) {
348 		ser_err("serialization cmd is null");
349 		goto error;
350 	}
351 	status = wlan_serialization_validate_cmd(cmd->source, cmd->cmd_type);
352 	if (QDF_IS_STATUS_ERROR(status)) {
353 		ser_err("cmd is not valid");
354 		goto error;
355 	}
356 
357 	psoc = wlan_serialization_get_psoc_from_cmd(cmd);
358 	if (!psoc) {
359 		ser_err("psoc _obj is invalid");
360 		return WLAN_SER_CMD_DENIED_UNSPECIFIED;
361 	}
362 	ser_soc_obj = wlan_serialization_get_psoc_obj(psoc);
363 
364 	if (!ser_soc_obj) {
365 		ser_err("ser_soc_obj is invalid");
366 		return WLAN_SER_CMD_DENIED_UNSPECIFIED;
367 	}
368 
369 	/*
370 	 * Get Component Info callback by calling
371 	 * each registered module
372 	 */
373 	for (comp_id = 0; comp_id < WLAN_UMAC_COMP_ID_MAX; comp_id++) {
374 		if (!ser_soc_obj->comp_info_cb[cmd->cmd_type][comp_id])
375 			continue;
376 		ser_soc_obj->comp_info_cb[cmd->cmd_type][comp_id](cmd->vdev,
377 			&info);
378 		if (!ser_soc_obj->apply_rules_cb[cmd->cmd_type])
379 			continue;
380 		if (!ser_soc_obj->apply_rules_cb[cmd->cmd_type](&info, comp_id))
381 			return WLAN_SER_CMD_DENIED_RULES_FAILED;
382 	}
383 
384 	serialization_status = wlan_serialization_enqueue_cmd(cmd, SER_REQUEST);
385 
386 error:
387 	ser_exit();
388 	return serialization_status;
389 }
390 
391 QDF_STATUS
392 wlan_serialization_update_timer(struct wlan_serialization_command *cmd)
393 {
394 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
395 	struct wlan_objmgr_pdev *pdev;
396 	struct wlan_objmgr_psoc *psoc;
397 
398 	if (!cmd) {
399 		ser_err("NULL command");
400 		goto error;
401 	}
402 
403 	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
404 	if (!pdev) {
405 		ser_err("invalid pdev");
406 		goto error;
407 	}
408 
409 	psoc = wlan_pdev_get_psoc(pdev);
410 	if (!psoc) {
411 		ser_err("invalid psoc");
412 		goto error;
413 	}
414 
415 	status = wlan_serialization_find_and_update_timer(psoc, cmd);
416 
417 error:
418 	return status;
419 }
420 
421 enum wlan_serialization_cmd_status
422 wlan_serialization_vdev_scan_status(struct wlan_objmgr_vdev *vdev)
423 {
424 	bool cmd_in_active = 0, cmd_in_pending = 0;
425 	struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev);
426 	struct wlan_ser_pdev_obj *ser_pdev_obj =
427 		wlan_serialization_get_pdev_obj(pdev);
428 	struct wlan_serialization_pdev_queue *pdev_q;
429 	enum wlan_serialization_cmd_status status;
430 
431 	ser_enter();
432 
433 	pdev_q = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN];
434 
435 	wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock);
436 
437 	cmd_in_active =
438 	wlan_serialization_is_cmd_in_vdev_list(
439 			vdev, &pdev_q->active_list, WLAN_SER_PDEV_NODE);
440 
441 	cmd_in_pending =
442 	wlan_serialization_is_cmd_in_vdev_list(
443 			vdev, &pdev_q->pending_list, WLAN_SER_PDEV_NODE);
444 
445 	status = wlan_serialization_is_cmd_in_active_pending(
446 			cmd_in_active, cmd_in_pending);
447 
448 	wlan_serialization_release_lock(&pdev_q->pdev_queue_lock);
449 	ser_exit();
450 
451 	return status;
452 }
453 
454 void wlan_serialization_flush_cmd(
455 		struct wlan_serialization_queued_cmd_info *cmd)
456 {
457 	ser_enter();
458 
459 	if (!cmd) {
460 		ser_err("cmd is null, can't flush");
461 		goto error;
462 	}
463 
464 error:
465 	ser_exit();
466 }
467 
468 enum wlan_serialization_cmd_status
469 wlan_serialization_pdev_scan_status(struct wlan_objmgr_pdev *pdev)
470 {
471 	bool cmd_in_active, cmd_in_pending;
472 	struct wlan_ser_pdev_obj *ser_pdev_obj =
473 		wlan_serialization_get_pdev_obj(pdev);
474 	struct wlan_serialization_pdev_queue *pdev_q;
475 	enum wlan_serialization_cmd_status status;
476 
477 	pdev_q = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN];
478 
479 	wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock);
480 
481 	cmd_in_active = !qdf_list_empty(&pdev_q->active_list);
482 	cmd_in_pending = !qdf_list_empty(&pdev_q->pending_list);
483 
484 	status = wlan_serialization_is_cmd_in_active_pending(
485 			cmd_in_active, cmd_in_pending);
486 
487 	wlan_serialization_release_lock(&pdev_q->pdev_queue_lock);
488 
489 	return status;
490 }
491 
492 struct wlan_serialization_command*
493 wlan_serialization_get_scan_cmd_using_scan_id(
494 		struct wlan_objmgr_psoc *psoc,
495 		uint8_t vdev_id, uint16_t scan_id,
496 		uint8_t is_scan_cmd_from_active_queue)
497 {
498 	struct wlan_objmgr_vdev *vdev;
499 	struct wlan_objmgr_pdev *pdev;
500 	struct wlan_ser_pdev_obj *ser_pdev_obj;
501 	struct wlan_serialization_command cmd = {0};
502 	struct wlan_serialization_command *pcmd = NULL;
503 	struct wlan_serialization_command_list *cmd_list;
504 	qdf_list_node_t *node = NULL;
505 	qdf_list_t *queue;
506 	struct wlan_serialization_pdev_queue *pdev_q;
507 
508 	if (!psoc) {
509 		ser_err("invalid psoc");
510 		goto error;
511 	}
512 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
513 						    WLAN_SERIALIZATION_ID);
514 	if (!vdev) {
515 		ser_err("invalid vdev");
516 		goto error;
517 	}
518 
519 	pdev = wlan_vdev_get_pdev(vdev);
520 	if (!pdev) {
521 		ser_err("invalid pdev");
522 		goto release_vdev_ref;
523 	}
524 
525 	ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev);
526 	if (!ser_pdev_obj) {
527 		ser_err("invalid ser_pdev_obj");
528 		goto release_vdev_ref;
529 	}
530 
531 	pdev_q = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN];
532 
533 	wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock);
534 
535 	if (is_scan_cmd_from_active_queue)
536 		queue = &pdev_q->active_list;
537 	else
538 		queue = &pdev_q->pending_list;
539 
540 	cmd.cmd_type = WLAN_SER_CMD_SCAN;
541 	cmd.cmd_id = scan_id;
542 	cmd.vdev = vdev;
543 
544 	node = wlan_serialization_find_cmd(
545 			queue, WLAN_SER_MATCH_CMD_ID_VDEV,
546 			&cmd, 0, NULL, vdev,  WLAN_SER_PDEV_NODE);
547 
548 	if (node) {
549 		cmd_list = qdf_container_of(
550 				node,
551 				struct wlan_serialization_command_list,
552 				pdev_node);
553 
554 		pcmd = &cmd_list->cmd;
555 	}
556 
557 	wlan_serialization_release_lock(&pdev_q->pdev_queue_lock);
558 
559 release_vdev_ref:
560 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SERIALIZATION_ID);
561 error:
562 	return pcmd;
563 }
564 
565 void *wlan_serialization_get_active_cmd(
566 		struct wlan_objmgr_psoc *psoc,
567 		uint8_t vdev_id,
568 		enum wlan_serialization_cmd_type cmd_type)
569 {
570 	struct wlan_objmgr_vdev *vdev;
571 	struct wlan_objmgr_pdev *pdev;
572 	struct wlan_ser_pdev_obj *ser_pdev_obj;
573 	struct wlan_serialization_command_list *cmd_list = NULL;
574 	void *umac_cmd = NULL;
575 	qdf_list_node_t *node = NULL;
576 	qdf_list_t *queue;
577 	struct wlan_serialization_pdev_queue *pdev_q;
578 
579 	ser_enter();
580 
581 	if (!psoc) {
582 		ser_err("invalid psoc");
583 		goto error;
584 	}
585 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
586 						    WLAN_SERIALIZATION_ID);
587 	if (!vdev) {
588 		ser_err("invalid vdev");
589 		goto error;
590 	}
591 
592 	pdev = wlan_vdev_get_pdev(vdev);
593 	if (!pdev) {
594 		ser_err("invalid pdev");
595 		goto release_vdev_ref;
596 	}
597 
598 	ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev);
599 	if (!ser_pdev_obj) {
600 		ser_err("invalid ser_pdev_obj");
601 		goto release_vdev_ref;
602 	}
603 
604 	pdev_q = wlan_serialization_get_pdev_queue_obj(ser_pdev_obj, cmd_type);
605 
606 	wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock);
607 
608 	queue = &pdev_q->active_list;
609 
610 	node = wlan_serialization_find_cmd(
611 			queue, WLAN_SER_MATCH_CMD_TYPE_VDEV,
612 			NULL, cmd_type, NULL, vdev,  WLAN_SER_PDEV_NODE);
613 
614 	if (node) {
615 		cmd_list = qdf_container_of(
616 				node,
617 				struct wlan_serialization_command_list,
618 				pdev_node);
619 
620 		umac_cmd = cmd_list->cmd.umac_cmd;
621 	}
622 
623 	wlan_serialization_release_lock(&pdev_q->pdev_queue_lock);
624 
625 release_vdev_ref:
626 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SERIALIZATION_ID);
627 error:
628 	ser_exit();
629 	return umac_cmd;
630 }
631 
632 enum wlan_serialization_cmd_type
633 wlan_serialization_get_vdev_active_cmd_type(struct wlan_objmgr_vdev *vdev)
634 {
635 	enum wlan_serialization_cmd_type cmd_type = WLAN_SER_CMD_MAX;
636 	struct wlan_ser_pdev_obj *ser_pdev_obj;
637 	struct wlan_ser_vdev_obj *ser_vdev_obj;
638 	struct wlan_serialization_pdev_queue *pdev_queue;
639 	struct wlan_serialization_vdev_queue *vdev_queue;
640 	struct wlan_serialization_command_list *cmd_list = NULL;
641 	qdf_list_node_t *node;
642 
643 	ser_pdev_obj = wlan_serialization_get_pdev_obj(
644 			wlan_vdev_get_pdev(vdev));
645 
646 	if (!ser_pdev_obj) {
647 		ser_err("invalid ser_pdev_obj");
648 		goto error;
649 	}
650 	pdev_queue = wlan_serialization_get_pdev_queue_obj(
651 			ser_pdev_obj, cmd_type);
652 
653 	ser_vdev_obj = wlan_serialization_get_vdev_obj(vdev);
654 	if (!ser_vdev_obj) {
655 		ser_err("invalid ser_vdev_obj");
656 		goto error;
657 	}
658 	vdev_queue = wlan_serialization_get_vdev_queue_obj(
659 			ser_vdev_obj, WLAN_SER_CMD_NONSCAN);
660 
661 	wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock);
662 
663 	if (wlan_serialization_peek_front(
664 		&vdev_queue->active_list, &node) == QDF_STATUS_SUCCESS) {
665 		cmd_list = qdf_container_of(
666 				node,
667 				struct wlan_serialization_command_list,
668 				vdev_node);
669 
670 		cmd_type = cmd_list->cmd.cmd_type;
671 	}
672 
673 	wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
674 
675 error:
676 	return cmd_type;
677 }
678 
679 bool wlan_ser_is_vdev_queue_enabled(struct wlan_objmgr_vdev *vdev)
680 {
681 	struct wlan_ser_vdev_obj *ser_vdev_obj;
682 	struct wlan_serialization_vdev_queue *vdev_queue;
683 
684 	ser_vdev_obj = wlan_serialization_get_vdev_obj(vdev);
685 	if (!ser_vdev_obj) {
686 		ser_err("invalid ser_vdev_obj");
687 		return false;
688 	}
689 
690 	vdev_queue = wlan_serialization_get_vdev_queue_obj(
691 			ser_vdev_obj, WLAN_SER_CMD_NONSCAN);
692 	if (vdev_queue->queue_disable)
693 		return false;
694 	else
695 		return true;
696 }
697 
698 QDF_STATUS
699 wlan_ser_get_cmd_activation_status(struct wlan_objmgr_vdev *vdev)
700 {
701 	struct wlan_ser_pdev_obj *ser_pdev_obj;
702 	struct wlan_ser_vdev_obj *ser_vdev_obj;
703 	struct wlan_serialization_pdev_queue *pdev_queue;
704 	struct wlan_serialization_vdev_queue *vdev_queue;
705 	struct wlan_serialization_command_list *cmd_list = NULL;
706 	qdf_list_node_t *node;
707 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
708 
709 	ser_pdev_obj = wlan_serialization_get_pdev_obj(
710 			wlan_vdev_get_pdev(vdev));
711 
712 	if (!ser_pdev_obj) {
713 		ser_err("invalid ser_pdev_obj");
714 		return QDF_STATUS_E_FAILURE;
715 	}
716 
717 	pdev_queue = wlan_serialization_get_pdev_queue_obj(
718 			ser_pdev_obj, WLAN_SER_CMD_NONSCAN);
719 
720 	ser_vdev_obj = wlan_serialization_get_vdev_obj(vdev);
721 	if (!ser_vdev_obj) {
722 		ser_err("invalid ser_vdev_obj");
723 		return QDF_STATUS_E_FAILURE;
724 	}
725 	vdev_queue = wlan_serialization_get_vdev_queue_obj(
726 			ser_vdev_obj, WLAN_SER_CMD_NONSCAN);
727 
728 	wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock);
729 
730 	if (wlan_serialization_peek_front(
731 		&vdev_queue->active_list, &node) == QDF_STATUS_SUCCESS) {
732 		cmd_list = qdf_container_of(
733 				node,
734 				struct wlan_serialization_command_list,
735 				vdev_node);
736 
737 		if (qdf_atomic_test_bit(CMD_MARKED_FOR_ACTIVATION,
738 					&cmd_list->cmd_in_use))
739 			status = QDF_STATUS_SUCCESS;
740 	}
741 
742 	wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
743 
744 	return status;
745 }
746 
747 QDF_STATUS
748 wlan_ser_validate_umac_cmd(struct wlan_objmgr_vdev *vdev,
749 			   enum wlan_serialization_cmd_type cmd_type,
750 			   wlan_ser_umac_cmd_cb umac_cmd_cb)
751 {
752 	struct wlan_objmgr_pdev *pdev;
753 	struct wlan_ser_pdev_obj *ser_pdev_obj;
754 	struct wlan_serialization_command_list *cmd_list = NULL;
755 	void *umac_cmd = NULL;
756 	qdf_list_node_t *node = NULL;
757 	qdf_list_t *queue;
758 	struct wlan_serialization_pdev_queue *pdev_q;
759 	QDF_STATUS status = QDF_STATUS_E_INVAL;
760 
761 	ser_enter();
762 
763 	if (!vdev) {
764 		ser_err("invalid vdev");
765 		return QDF_STATUS_E_INVAL;
766 	}
767 
768 	pdev = wlan_vdev_get_pdev(vdev);
769 	if (!pdev) {
770 		ser_err("invalid pdev");
771 		return QDF_STATUS_E_INVAL;
772 	}
773 
774 	ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev);
775 	if (!ser_pdev_obj) {
776 		ser_err("invalid ser_pdev_obj");
777 		return QDF_STATUS_E_INVAL;
778 	}
779 
780 	pdev_q = wlan_serialization_get_pdev_queue_obj(ser_pdev_obj, cmd_type);
781 
782 	wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock);
783 
784 	queue = &pdev_q->active_list;
785 	node = wlan_serialization_find_cmd(
786 			queue, WLAN_SER_MATCH_CMD_TYPE_VDEV,
787 			NULL, cmd_type, NULL, vdev,  WLAN_SER_PDEV_NODE);
788 	if (node) {
789 		cmd_list = qdf_container_of(
790 				node,
791 				struct wlan_serialization_command_list,
792 				pdev_node);
793 
794 		umac_cmd = cmd_list->cmd.umac_cmd;
795 		status = umac_cmd_cb(umac_cmd);
796 	}
797 
798 	wlan_serialization_release_lock(&pdev_q->pdev_queue_lock);
799 	ser_exit();
800 
801 	return status;
802 }
803 
804 void wlan_serialization_purge_all_pdev_cmd(struct wlan_objmgr_pdev *pdev)
805 {
806 	struct wlan_ser_pdev_obj *ser_pdev_obj;
807 
808 	if (!pdev) {
809 		ser_err("NULL pdev");
810 		return;
811 	}
812 
813 	ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev);
814 	if (!ser_pdev_obj) {
815 		ser_err("invalid ser_pdev_obj");
816 		return;
817 	}
818 
819 	wlan_ser_cancel_scan_cmd(ser_pdev_obj, pdev, NULL, NULL,
820 				 WLAN_SER_CMD_SCAN, false);
821 	wlan_ser_cancel_scan_cmd(ser_pdev_obj, pdev, NULL, NULL,
822 				 WLAN_SER_CMD_SCAN, true);
823 	wlan_ser_cancel_non_scan_cmd(ser_pdev_obj, pdev, NULL, NULL,
824 				     WLAN_SER_CMD_NONSCAN, false,
825 				     WLAN_SER_CMD_ATTR_NONE);
826 	wlan_ser_cancel_non_scan_cmd(ser_pdev_obj, pdev, NULL, NULL,
827 				     WLAN_SER_CMD_NONSCAN, true,
828 				     WLAN_SER_CMD_ATTR_NONE);
829 }
830 
831 static inline
832 void wlan_ser_purge_pdev_cmd_cb(struct wlan_objmgr_psoc *psoc,
833 				void *object, void *arg)
834 {
835 	struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)object;
836 
837 	wlan_serialization_purge_all_pdev_cmd(pdev);
838 }
839 
840 void wlan_serialization_purge_all_cmd(struct wlan_objmgr_psoc *psoc)
841 {
842 	wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
843 				     wlan_ser_purge_pdev_cmd_cb, NULL, 1,
844 				     WLAN_SERIALIZATION_ID);
845 }
846 
847 void wlan_serialization_purge_all_pending_cmd_by_vdev_id(
848 					struct wlan_objmgr_pdev *pdev,
849 					uint8_t vdev_id)
850 {
851 	struct wlan_objmgr_vdev *vdev;
852 	struct wlan_ser_pdev_obj *ser_pdev_obj;
853 
854 	if (!pdev) {
855 		ser_err("Invalid pdev");
856 		return;
857 	}
858 
859 	ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev);
860 	if (!ser_pdev_obj) {
861 		ser_err("invalid ser_pdev_obj");
862 		return;
863 	}
864 
865 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id,
866 						    WLAN_SERIALIZATION_ID);
867 	if (!vdev) {
868 		ser_err("Invalid vdev");
869 		return;
870 	}
871 
872 	wlan_ser_cancel_scan_cmd(ser_pdev_obj, pdev, vdev, NULL,
873 				 WLAN_SER_CMD_SCAN, false);
874 	wlan_ser_cancel_non_scan_cmd(ser_pdev_obj, pdev, vdev, NULL,
875 				     WLAN_SER_CMD_NONSCAN, false,
876 				     WLAN_SER_CMD_ATTR_NONE);
877 
878 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SERIALIZATION_ID);
879 }
880 
881 void wlan_serialization_purge_all_scan_cmd_by_vdev_id(
882 					struct wlan_objmgr_pdev *pdev,
883 					uint8_t vdev_id)
884 {
885 	struct wlan_objmgr_vdev *vdev;
886 	struct wlan_ser_pdev_obj *ser_pdev_obj;
887 
888 	if (!pdev) {
889 		ser_err("Invalid pdev");
890 		return;
891 	}
892 
893 	ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev);
894 	if (!ser_pdev_obj) {
895 		ser_err("invalid ser_pdev_obj");
896 		return;
897 	}
898 
899 	vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id,
900 						    WLAN_SERIALIZATION_ID);
901 	if (!vdev) {
902 		ser_err("Invalid vdev");
903 		return;
904 	}
905 
906 	wlan_ser_cancel_scan_cmd(ser_pdev_obj, pdev, vdev, NULL,
907 				 WLAN_SER_CMD_SCAN, false);
908 	wlan_ser_cancel_scan_cmd(ser_pdev_obj, pdev, vdev, NULL,
909 				 WLAN_SER_CMD_SCAN, true);
910 
911 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SERIALIZATION_ID);
912 }
913 
914 QDF_STATUS wlan_ser_vdev_queue_disable(struct wlan_objmgr_vdev *vdev)
915 {
916 	struct wlan_objmgr_pdev *pdev;
917 	struct wlan_ser_vdev_obj *ser_vdev_obj;
918 	struct wlan_serialization_vdev_queue *vdev_queue;
919 	struct wlan_ser_pdev_obj *ser_pdev_obj;
920 	struct wlan_serialization_pdev_queue *pdev_q;
921 
922 	pdev = wlan_vdev_get_pdev(vdev);
923 	if (!pdev) {
924 		ser_err("invalid PDEV object");
925 		return QDF_STATUS_E_INVAL;
926 	}
927 
928 	ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev);
929 	if (!ser_pdev_obj) {
930 		ser_err("invalid ser_pdev_obj");
931 		return QDF_STATUS_E_INVAL;
932 	}
933 
934 	ser_vdev_obj = wlan_serialization_get_vdev_obj(vdev);
935 	if (!ser_vdev_obj) {
936 		ser_err("invalid ser_vdev_obj");
937 		return QDF_STATUS_E_INVAL;
938 	}
939 
940 	pdev_q = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN];
941 
942 	vdev_queue = wlan_serialization_get_vdev_queue_obj(
943 			ser_vdev_obj, WLAN_SER_CMD_NONSCAN);
944 	if (!vdev_queue) {
945 		ser_err("invalid vdev_queue object");
946 		return QDF_STATUS_E_INVAL;
947 	}
948 
949 	wlan_serialization_acquire_lock(&pdev_q->pdev_queue_lock);
950 	vdev_queue->queue_disable = true;
951 	wlan_serialization_release_lock(&pdev_q->pdev_queue_lock);
952 	ser_info("Disabling the serialization for vdev:%d",
953 		 wlan_vdev_get_id(vdev));
954 
955 	return QDF_STATUS_SUCCESS;
956 }
957