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