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