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