1 /*
2 * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2022-2023 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_utils.c
22 * This file defines the utility helper functions for serialization component.
23 */
24
25 #include <wlan_objmgr_vdev_obj.h>
26 #include <wlan_objmgr_pdev_obj.h>
27 #include <qdf_mc_timer.h>
28 #include <wlan_utility.h>
29 #include "wlan_serialization_utils_i.h"
30 #include "wlan_serialization_main_i.h"
31 #include "wlan_serialization_queue_i.h"
32 #include "wlan_serialization_api.h"
33
34 #ifndef WLAN_SER_DEBUG
wlan_ser_update_cmd_history(struct wlan_serialization_pdev_queue * pdev_queue,struct wlan_serialization_command * cmd,enum ser_queue_reason ser_reason,bool add_remove,bool active_queue)35 void wlan_ser_update_cmd_history(
36 struct wlan_serialization_pdev_queue *pdev_queue,
37 struct wlan_serialization_command *cmd,
38 enum ser_queue_reason ser_reason,
39 bool add_remove,
40 bool active_queue){ }
41 #endif
42
43 struct wlan_objmgr_pdev*
wlan_serialization_get_pdev_from_cmd(struct wlan_serialization_command * cmd)44 wlan_serialization_get_pdev_from_cmd(struct wlan_serialization_command *cmd)
45 {
46 struct wlan_objmgr_pdev *pdev = NULL;
47
48 if (!cmd) {
49 ser_err("invalid cmd");
50 return pdev;
51 }
52 if (!cmd->vdev) {
53 ser_err("invalid cmd->vdev");
54 return pdev;
55 }
56 pdev = wlan_vdev_get_pdev(cmd->vdev);
57
58 return pdev;
59 }
60
61 struct wlan_objmgr_psoc*
wlan_serialization_get_psoc_from_cmd(struct wlan_serialization_command * cmd)62 wlan_serialization_get_psoc_from_cmd(struct wlan_serialization_command *cmd)
63 {
64 struct wlan_objmgr_psoc *psoc = NULL;
65
66 if (!cmd) {
67 ser_err("invalid cmd");
68 return psoc;
69 }
70 if (!cmd->vdev) {
71 ser_err("invalid cmd->vdev");
72 return psoc;
73 }
74 psoc = wlan_vdev_get_psoc(cmd->vdev);
75
76 return psoc;
77 }
78
79 struct wlan_objmgr_vdev*
wlan_serialization_get_vdev_from_cmd(struct wlan_serialization_command * cmd)80 wlan_serialization_get_vdev_from_cmd(struct wlan_serialization_command *cmd)
81 {
82 struct wlan_objmgr_vdev *vdev = NULL;
83
84 if (!cmd) {
85 ser_err("invalid cmd");
86 goto error;
87 }
88
89 vdev = cmd->vdev;
90
91 error:
92 return vdev;
93 }
94
95 QDF_STATUS
wlan_serialization_get_cmd_from_queue(qdf_list_t * queue,qdf_list_node_t ** nnode)96 wlan_serialization_get_cmd_from_queue(qdf_list_t *queue,
97 qdf_list_node_t **nnode)
98 {
99 QDF_STATUS status = QDF_STATUS_E_FAILURE;
100 qdf_list_node_t *pnode;
101
102 if (!queue) {
103 ser_err("input parameters are invalid");
104 goto error;
105 }
106
107 pnode = *nnode;
108 if (!pnode)
109 status = wlan_serialization_peek_front(queue, nnode);
110 else
111 status = wlan_serialization_peek_next(queue, pnode, nnode);
112
113 if (status != QDF_STATUS_SUCCESS)
114 ser_err("can't get next node from queue");
115
116 error:
117 return status;
118 }
119
wlan_serialization_timer_destroy(struct wlan_serialization_timer * ser_timer)120 QDF_STATUS wlan_serialization_timer_destroy(
121 struct wlan_serialization_timer *ser_timer)
122 {
123 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
124
125 if (!ser_timer || !ser_timer->cmd) {
126 ser_debug("Invalid ser_timer");
127 qdf_status = QDF_STATUS_E_FAILURE;
128 goto error;
129 }
130 /* Wait till timeout CB is completed */
131 qdf_timer_sync_cancel(&ser_timer->timer);
132 ser_timer->cmd = NULL;
133
134 error:
135 return qdf_status;
136 }
137
138 QDF_STATUS
wlan_serialization_stop_timer(struct wlan_serialization_timer * ser_timer)139 wlan_serialization_stop_timer(struct wlan_serialization_timer *ser_timer)
140 {
141 wlan_serialization_timer_destroy(ser_timer);
142
143 return QDF_STATUS_SUCCESS;
144 }
145
wlan_serialization_cleanup_vdev_timers(struct wlan_objmgr_vdev * vdev)146 QDF_STATUS wlan_serialization_cleanup_vdev_timers(
147 struct wlan_objmgr_vdev *vdev)
148 {
149 struct wlan_ser_psoc_obj *psoc_ser_obj;
150 struct wlan_serialization_timer *ser_timer;
151 QDF_STATUS status = QDF_STATUS_SUCCESS;
152 uint32_t i = 0;
153 struct wlan_objmgr_pdev *pdev = NULL;
154 struct wlan_objmgr_psoc *psoc = NULL;
155
156 pdev = wlan_vdev_get_pdev(vdev);
157 if (!pdev) {
158 QDF_BUG(0);
159 ser_err("pdev is null");
160 status = QDF_STATUS_E_FAILURE;
161 goto error;
162 }
163
164 psoc = wlan_pdev_get_psoc(pdev);
165 if (!psoc) {
166 QDF_BUG(0);
167 ser_err("psoc is null");
168 status = QDF_STATUS_E_FAILURE;
169 goto error;
170 }
171
172 psoc_ser_obj = wlan_serialization_get_psoc_obj(psoc);
173
174 if (!psoc_ser_obj) {
175 ser_err("Invalid psoc_ser_obj");
176 status = QDF_STATUS_E_FAILURE;
177 goto error;
178 }
179
180 wlan_serialization_acquire_lock(&psoc_ser_obj->timer_lock);
181
182 for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) {
183 ser_timer = &psoc_ser_obj->timers[i];
184 if (!ser_timer->cmd)
185 continue;
186 /*
187 * Check if the timer is for the given vdev
188 */
189 if (ser_timer->cmd->vdev != vdev)
190 continue;
191
192 ser_debug("Stopping the timer for vdev id[%d]",
193 wlan_vdev_get_id(vdev));
194
195 status = wlan_serialization_stop_timer(ser_timer);
196 if (QDF_STATUS_SUCCESS != status) {
197 /* lets not break the loop but report error */
198 ser_err("some error in stopping timer");
199 }
200 }
201
202 wlan_serialization_release_lock(&psoc_ser_obj->timer_lock);
203 error:
204 return status;
205 }
206
wlan_serialization_cleanup_all_timers(struct wlan_ser_psoc_obj * psoc_ser_obj)207 QDF_STATUS wlan_serialization_cleanup_all_timers(
208 struct wlan_ser_psoc_obj *psoc_ser_obj)
209 {
210 struct wlan_serialization_timer *ser_timer;
211 QDF_STATUS status = QDF_STATUS_SUCCESS;
212 uint32_t i = 0;
213
214 if (!psoc_ser_obj) {
215 ser_err("Invalid psoc_ser_obj");
216 status = QDF_STATUS_E_FAILURE;
217 goto error;
218 }
219
220 wlan_serialization_acquire_lock(&psoc_ser_obj->timer_lock);
221
222 for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) {
223 ser_timer = &psoc_ser_obj->timers[i];
224 if (!ser_timer->cmd)
225 continue;
226 status = wlan_serialization_stop_timer(ser_timer);
227 if (QDF_STATUS_SUCCESS != status) {
228 /* lets not break the loop but report error */
229 ser_err("some error in stopping timer");
230 }
231 }
232
233 wlan_serialization_release_lock(&psoc_ser_obj->timer_lock);
234 error:
235
236 return status;
237 }
238
wlan_serialization_validate_cmdtype(enum wlan_serialization_cmd_type cmd_type)239 QDF_STATUS wlan_serialization_validate_cmdtype(
240 enum wlan_serialization_cmd_type cmd_type)
241 {
242 if (cmd_type < 0 || cmd_type >= WLAN_SER_CMD_MAX) {
243 ser_err("Invalid cmd %d passed", cmd_type);
244 return QDF_STATUS_E_INVAL;
245 }
246
247 return QDF_STATUS_SUCCESS;
248 }
249
wlan_serialization_validate_cmd(enum wlan_umac_comp_id comp_id,enum wlan_serialization_cmd_type cmd_type)250 QDF_STATUS wlan_serialization_validate_cmd(
251 enum wlan_umac_comp_id comp_id,
252 enum wlan_serialization_cmd_type cmd_type)
253 {
254 QDF_STATUS status = QDF_STATUS_E_INVAL;
255
256 if (cmd_type < 0 || comp_id < 0 || cmd_type >= WLAN_SER_CMD_MAX ||
257 comp_id >= WLAN_UMAC_COMP_ID_MAX) {
258 ser_err("Invalid cmd or comp passed comp %d type %d",
259 comp_id, cmd_type);
260 goto error;
261 }
262
263 status = QDF_STATUS_SUCCESS;
264 error:
265 return status;
266 }
267
wlan_serialization_validate_cmd_list(struct wlan_serialization_command_list * cmd_list)268 QDF_STATUS wlan_serialization_validate_cmd_list(
269 struct wlan_serialization_command_list *cmd_list)
270 {
271 QDF_STATUS status = QDF_STATUS_E_INVAL;
272
273 if (!cmd_list->cmd.cmd_cb) {
274 ser_err("no cmd_cb for cmd type:%d, id: %d",
275 cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id);
276 QDF_ASSERT(0);
277 goto error;
278 }
279
280 if (!cmd_list->cmd.vdev) {
281 ser_err("invalid cmd.vdev");
282 goto error;
283 }
284
285 status = QDF_STATUS_SUCCESS;
286
287 error:
288 return status;
289 }
290
wlan_serialization_release_pdev_list_cmds(struct wlan_serialization_pdev_queue * pdev_queue)291 static void wlan_serialization_release_pdev_list_cmds(
292 struct wlan_serialization_pdev_queue *pdev_queue)
293 {
294 qdf_list_node_t *node = NULL;
295
296 while (!wlan_serialization_list_empty(&pdev_queue->active_list)) {
297 wlan_serialization_remove_front(
298 &pdev_queue->active_list, &node);
299 wlan_serialization_insert_back(
300 &pdev_queue->cmd_pool_list, node);
301 }
302
303 while (!wlan_serialization_list_empty(&pdev_queue->pending_list)) {
304 wlan_serialization_remove_front(
305 &pdev_queue->pending_list, &node);
306 wlan_serialization_insert_back(
307 &pdev_queue->cmd_pool_list, node);
308 }
309
310 }
311
wlan_serialization_release_vdev_list_cmds(qdf_list_t * list)312 static void wlan_serialization_release_vdev_list_cmds(qdf_list_t *list)
313 {
314 qdf_list_node_t *node = NULL;
315
316
317 while (!wlan_serialization_list_empty(list))
318 wlan_serialization_remove_front(list, &node);
319
320 }
321
wlan_serialization_destroy_pdev_list(struct wlan_serialization_pdev_queue * pdev_queue)322 void wlan_serialization_destroy_pdev_list(
323 struct wlan_serialization_pdev_queue *pdev_queue)
324 {
325
326 wlan_serialization_release_pdev_list_cmds(pdev_queue);
327 qdf_list_destroy(&pdev_queue->pending_list);
328 qdf_list_destroy(&pdev_queue->active_list);
329
330 }
331
wlan_serialization_destroy_vdev_list(qdf_list_t * list)332 void wlan_serialization_destroy_vdev_list(qdf_list_t *list)
333 {
334
335 wlan_serialization_release_vdev_list_cmds(list);
336 qdf_list_destroy(list);
337
338 }
339
wlan_serialization_get_psoc_obj(struct wlan_objmgr_psoc * psoc)340 struct wlan_ser_psoc_obj *wlan_serialization_get_psoc_obj(
341 struct wlan_objmgr_psoc *psoc)
342 {
343 struct wlan_ser_psoc_obj *ser_soc_obj;
344
345 ser_soc_obj =
346 wlan_objmgr_psoc_get_comp_private_obj(
347 psoc, WLAN_UMAC_COMP_SERIALIZATION);
348
349 return ser_soc_obj;
350 }
351
wlan_serialization_get_pdev_obj(struct wlan_objmgr_pdev * pdev)352 struct wlan_ser_pdev_obj *wlan_serialization_get_pdev_obj(
353 struct wlan_objmgr_pdev *pdev)
354 {
355 struct wlan_ser_pdev_obj *obj;
356
357 obj = wlan_objmgr_pdev_get_comp_private_obj(
358 pdev, WLAN_UMAC_COMP_SERIALIZATION);
359
360 return obj;
361 }
362
wlan_serialization_get_vdev_obj(struct wlan_objmgr_vdev * vdev)363 struct wlan_ser_vdev_obj *wlan_serialization_get_vdev_obj(
364 struct wlan_objmgr_vdev *vdev)
365 {
366 struct wlan_ser_vdev_obj *obj;
367
368 obj = wlan_objmgr_vdev_get_comp_private_obj(
369 vdev, WLAN_UMAC_COMP_SERIALIZATION);
370
371 return obj;
372 }
373
wlan_serialization_is_cmd_in_vdev_list(struct wlan_objmgr_vdev * vdev,qdf_list_t * queue,enum wlan_serialization_node node_type)374 bool wlan_serialization_is_cmd_in_vdev_list(
375 struct wlan_objmgr_vdev *vdev,
376 qdf_list_t *queue,
377 enum wlan_serialization_node node_type)
378 {
379 qdf_list_node_t *node = NULL;
380 bool cmd_found = false;
381
382 node = wlan_serialization_find_cmd(
383 queue, WLAN_SER_MATCH_VDEV,
384 NULL, 0, NULL, vdev, node_type);
385
386 if (node)
387 cmd_found = true;
388
389 return cmd_found;
390 }
391
wlan_serialization_is_cmd_in_pdev_list(struct wlan_objmgr_pdev * pdev,qdf_list_t * queue)392 bool wlan_serialization_is_cmd_in_pdev_list(
393 struct wlan_objmgr_pdev *pdev,
394 qdf_list_t *queue)
395 {
396 qdf_list_node_t *node = NULL;
397 bool cmd_found = false;
398
399 node = wlan_serialization_find_cmd(
400 queue, WLAN_SER_MATCH_PDEV,
401 NULL, 0, pdev, NULL, WLAN_SER_PDEV_NODE);
402
403 if (node)
404 cmd_found = true;
405
406 return cmd_found;
407 }
408
409 enum wlan_serialization_cmd_status
wlan_serialization_is_cmd_in_active_pending(bool cmd_in_active,bool cmd_in_pending)410 wlan_serialization_is_cmd_in_active_pending(bool cmd_in_active,
411 bool cmd_in_pending)
412 {
413 enum wlan_serialization_cmd_status status;
414
415 if (cmd_in_active && cmd_in_pending)
416 status = WLAN_SER_CMDS_IN_ALL_LISTS;
417 else if (cmd_in_active)
418 status = WLAN_SER_CMD_IN_ACTIVE_LIST;
419 else if (cmd_in_pending)
420 status = WLAN_SER_CMD_IN_PENDING_LIST;
421 else
422 status = WLAN_SER_CMD_NOT_FOUND;
423
424 return status;
425 }
426
427 bool
wlan_serialization_is_cmd_present_in_given_queue(qdf_list_t * queue,struct wlan_serialization_command * cmd,enum wlan_serialization_node node_type)428 wlan_serialization_is_cmd_present_in_given_queue(
429 qdf_list_t *queue,
430 struct wlan_serialization_command *cmd,
431 enum wlan_serialization_node node_type)
432 {
433 qdf_list_node_t *node = NULL;
434 bool found = false;
435
436 node = wlan_serialization_find_cmd(
437 queue, WLAN_SER_MATCH_CMD_ID_VDEV,
438 cmd, 0, NULL, cmd->vdev, node_type);
439
440 if (node)
441 found = true;
442
443 return found;
444 }
445
446 QDF_STATUS
wlan_serialization_remove_cmd_from_queue(qdf_list_t * queue,struct wlan_serialization_command * cmd,struct wlan_serialization_command_list ** pcmd_list,struct wlan_ser_pdev_obj * ser_pdev_obj,enum wlan_serialization_node node_type)447 wlan_serialization_remove_cmd_from_queue(
448 qdf_list_t *queue,
449 struct wlan_serialization_command *cmd,
450 struct wlan_serialization_command_list **pcmd_list,
451 struct wlan_ser_pdev_obj *ser_pdev_obj,
452 enum wlan_serialization_node node_type)
453 {
454 struct wlan_serialization_command_list *cmd_list;
455 qdf_list_node_t *node = NULL;
456 QDF_STATUS status = QDF_STATUS_E_FAILURE;
457
458 if (!cmd)
459 goto error;
460
461 if (!queue || wlan_serialization_list_empty(queue)) {
462 ser_debug("Empty queue");
463 goto error;
464 }
465
466 node = wlan_serialization_find_cmd(queue, WLAN_SER_MATCH_CMD_ID_VDEV,
467 cmd, 0, NULL, cmd->vdev, node_type);
468
469 if (!node) {
470 ser_info("fail to find node %d for removal", node_type);
471 goto error;
472 }
473
474 if (node_type == WLAN_SER_PDEV_NODE)
475 cmd_list =
476 qdf_container_of(node,
477 struct wlan_serialization_command_list,
478 pdev_node);
479 else
480 cmd_list =
481 qdf_container_of(node,
482 struct wlan_serialization_command_list,
483 vdev_node);
484
485 if (qdf_atomic_test_bit(CMD_MARKED_FOR_ACTIVATION,
486 &cmd_list->cmd_in_use)) {
487 qdf_atomic_set_bit(CMD_ACTIVE_MARKED_FOR_REMOVAL,
488 &cmd_list->cmd_in_use);
489 status = QDF_STATUS_E_PENDING;
490 goto error;
491 }
492
493 status = wlan_serialization_remove_node(queue, node);
494
495 if (QDF_STATUS_SUCCESS != status)
496 ser_err("Fail to add to free pool type %d",
497 cmd->cmd_type);
498
499 *pcmd_list = cmd_list;
500
501 error:
502 return status;
503 }
504
505 enum wlan_serialization_status
wlan_serialization_add_cmd_to_queue(qdf_list_t * queue,struct wlan_serialization_command_list * cmd_list,struct wlan_ser_pdev_obj * ser_pdev_obj,uint8_t is_cmd_for_active_queue,enum wlan_serialization_node node_type)506 wlan_serialization_add_cmd_to_queue(
507 qdf_list_t *queue,
508 struct wlan_serialization_command_list *cmd_list,
509 struct wlan_ser_pdev_obj *ser_pdev_obj,
510 uint8_t is_cmd_for_active_queue,
511 enum wlan_serialization_node node_type)
512 {
513 enum wlan_serialization_status status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
514 QDF_STATUS qdf_status;
515 qdf_list_node_t *node;
516
517 if (!cmd_list || !queue || !ser_pdev_obj) {
518 ser_err("Input arguments are not valid");
519 goto error;
520 }
521
522 if (node_type == WLAN_SER_PDEV_NODE)
523 node = &cmd_list->pdev_node;
524 else
525 node = &cmd_list->vdev_node;
526
527 if (qdf_list_size(queue) == qdf_list_max_size(queue)) {
528 status = WLAN_SER_CMD_DENIED_LIST_FULL;
529 ser_err("Queue size reached max %d, fail to add type %d id %d",
530 qdf_list_max_size(queue), cmd_list->cmd.cmd_type,
531 cmd_list->cmd.cmd_id);
532 goto error;
533 }
534
535 if (cmd_list->cmd.is_high_priority)
536 qdf_status = wlan_serialization_insert_front(queue, node);
537 else
538 qdf_status = wlan_serialization_insert_back(queue, node);
539
540 if (QDF_IS_STATUS_ERROR(qdf_status))
541 goto error;
542
543 if (is_cmd_for_active_queue)
544 status = WLAN_SER_CMD_ACTIVE;
545 else
546 status = WLAN_SER_CMD_PENDING;
547
548 error:
549 return status;
550 }
551
wlan_serialization_list_empty(qdf_list_t * queue)552 bool wlan_serialization_list_empty(qdf_list_t *queue)
553 {
554 bool is_empty;
555
556 if (qdf_list_empty(queue))
557 is_empty = true;
558 else
559 is_empty = false;
560
561 return is_empty;
562 }
563
wlan_serialization_list_size(qdf_list_t * queue)564 uint32_t wlan_serialization_list_size(qdf_list_t *queue)
565 {
566 uint32_t size;
567
568 size = qdf_list_size(queue);
569
570 return size;
571 }
572
wlan_serialization_remove_front(qdf_list_t * list,qdf_list_node_t ** node)573 QDF_STATUS wlan_serialization_remove_front(qdf_list_t *list,
574 qdf_list_node_t **node)
575 {
576 QDF_STATUS status;
577
578 if (wlan_serialization_list_empty(list)) {
579 ser_err("The list is empty");
580 status = QDF_STATUS_E_EMPTY;
581 goto error;
582 }
583
584 status = qdf_list_remove_front(list, node);
585 error:
586 return status;
587 }
588
wlan_serialization_remove_node(qdf_list_t * list,qdf_list_node_t * node)589 QDF_STATUS wlan_serialization_remove_node(qdf_list_t *list,
590 qdf_list_node_t *node)
591 {
592 QDF_STATUS status;
593
594 if (wlan_serialization_list_empty(list)) {
595 ser_err("The list is empty");
596 status = QDF_STATUS_E_EMPTY;
597 goto error;
598 }
599 status = qdf_list_remove_node(list, node);
600
601 error:
602 return status;
603 }
604
wlan_serialization_insert_front(qdf_list_t * list,qdf_list_node_t * node)605 QDF_STATUS wlan_serialization_insert_front(qdf_list_t *list,
606 qdf_list_node_t *node)
607 {
608 QDF_STATUS status;
609
610 status = qdf_list_insert_front(list, node);
611
612 return status;
613 }
614
wlan_serialization_insert_back(qdf_list_t * list,qdf_list_node_t * node)615 QDF_STATUS wlan_serialization_insert_back(qdf_list_t *list,
616 qdf_list_node_t *node)
617 {
618 QDF_STATUS status;
619
620 status = qdf_list_insert_back(list, node);
621
622 return status;
623 }
624
wlan_serialization_peek_front(qdf_list_t * list,qdf_list_node_t ** node)625 QDF_STATUS wlan_serialization_peek_front(qdf_list_t *list,
626 qdf_list_node_t **node)
627 {
628 QDF_STATUS status;
629
630 status = qdf_list_peek_front(list, node);
631
632 return status;
633 }
634
wlan_serialization_peek_next(qdf_list_t * list,qdf_list_node_t * node1,qdf_list_node_t ** node2)635 QDF_STATUS wlan_serialization_peek_next(qdf_list_t *list,
636 qdf_list_node_t *node1,
637 qdf_list_node_t **node2)
638 {
639 QDF_STATUS status;
640
641 status = qdf_list_peek_next(list, node1, node2);
642
643 return status;
644 }
645
646 bool
wlan_serialization_match_cmd_type(qdf_list_node_t * nnode,enum wlan_serialization_cmd_type cmd_type,enum wlan_serialization_node node_type)647 wlan_serialization_match_cmd_type(qdf_list_node_t *nnode,
648 enum wlan_serialization_cmd_type cmd_type,
649 enum wlan_serialization_node node_type)
650 {
651 struct wlan_serialization_command_list *cmd_list = NULL;
652 bool match_found = true;
653
654 if (node_type == WLAN_SER_PDEV_NODE)
655 cmd_list =
656 qdf_container_of(nnode,
657 struct wlan_serialization_command_list,
658 pdev_node);
659 else
660 cmd_list =
661 qdf_container_of(nnode,
662 struct wlan_serialization_command_list,
663 vdev_node);
664
665 if (cmd_list->cmd.cmd_type != cmd_type)
666 match_found = false;
667
668 return match_found;
669 }
670
671 bool
wlan_serialization_match_cmd_id_type(qdf_list_node_t * nnode,struct wlan_serialization_command * cmd,enum wlan_serialization_node node_type)672 wlan_serialization_match_cmd_id_type(qdf_list_node_t *nnode,
673 struct wlan_serialization_command *cmd,
674 enum wlan_serialization_node node_type)
675 {
676 struct wlan_serialization_command_list *cmd_list = NULL;
677 bool match_found = true;
678
679 if (!cmd) {
680 match_found = false;
681 goto error;
682 }
683
684 if (node_type == WLAN_SER_PDEV_NODE)
685 cmd_list =
686 qdf_container_of(nnode,
687 struct wlan_serialization_command_list,
688 pdev_node);
689 else
690 cmd_list =
691 qdf_container_of(nnode,
692 struct wlan_serialization_command_list,
693 vdev_node);
694
695 if ((cmd_list->cmd.cmd_id != cmd->cmd_id) ||
696 (cmd_list->cmd.cmd_type != cmd->cmd_type)) {
697 match_found = false;
698 };
699
700 error:
701 return match_found;
702 }
703
wlan_serialization_match_cmd_vdev(qdf_list_node_t * nnode,struct wlan_objmgr_vdev * vdev,enum wlan_serialization_node node_type)704 bool wlan_serialization_match_cmd_vdev(qdf_list_node_t *nnode,
705 struct wlan_objmgr_vdev *vdev,
706 enum wlan_serialization_node node_type)
707 {
708 struct wlan_serialization_command_list *cmd_list = NULL;
709 bool match_found = false;
710
711 if (node_type == WLAN_SER_PDEV_NODE)
712 cmd_list =
713 qdf_container_of(nnode,
714 struct wlan_serialization_command_list,
715 pdev_node);
716 else
717 cmd_list =
718 qdf_container_of(nnode,
719 struct wlan_serialization_command_list,
720 vdev_node);
721
722 if (cmd_list->cmd.vdev == vdev)
723 match_found = true;
724
725 if (!match_found)
726 ser_debug("matching cmd not found for (vdev:%pK)", vdev);
727
728 return match_found;
729 }
730
wlan_serialization_match_cmd_pdev(qdf_list_node_t * nnode,struct wlan_objmgr_pdev * pdev,enum wlan_serialization_node node_type)731 bool wlan_serialization_match_cmd_pdev(qdf_list_node_t *nnode,
732 struct wlan_objmgr_pdev *pdev,
733 enum wlan_serialization_node node_type)
734 {
735 struct wlan_serialization_command_list *cmd_list = NULL;
736 bool match_found = false;
737 struct wlan_objmgr_pdev *node_pdev = NULL;
738
739 if (node_type == WLAN_SER_PDEV_NODE)
740 cmd_list =
741 qdf_container_of(nnode,
742 struct wlan_serialization_command_list,
743 pdev_node);
744 else
745 cmd_list =
746 qdf_container_of(nnode,
747 struct wlan_serialization_command_list,
748 vdev_node);
749
750 node_pdev = wlan_vdev_get_pdev(cmd_list->cmd.vdev);
751 if (node_pdev == pdev)
752 match_found = true;
753
754 return match_found;
755 }
756
wlan_serialization_match_cmd_blocking(qdf_list_node_t * nnode,enum wlan_serialization_node node_type)757 bool wlan_serialization_match_cmd_blocking(
758 qdf_list_node_t *nnode,
759 enum wlan_serialization_node node_type)
760 {
761 struct wlan_serialization_command_list *cmd_list = NULL;
762 bool match_found = false;
763
764 if (node_type == WLAN_SER_PDEV_NODE)
765 cmd_list =
766 qdf_container_of(nnode,
767 struct wlan_serialization_command_list,
768 pdev_node);
769 else
770 cmd_list =
771 qdf_container_of(nnode,
772 struct wlan_serialization_command_list,
773 vdev_node);
774
775 if (cmd_list->cmd.is_blocking)
776 match_found = true;
777
778 return match_found;
779 }
780
781 qdf_list_node_t *
wlan_serialization_find_cmd(qdf_list_t * queue,enum wlan_serialization_match_type match_type,struct wlan_serialization_command * cmd,enum wlan_serialization_cmd_type cmd_type,struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_vdev * vdev,enum wlan_serialization_node node_type)782 wlan_serialization_find_cmd(qdf_list_t *queue,
783 enum wlan_serialization_match_type match_type,
784 struct wlan_serialization_command *cmd,
785 enum wlan_serialization_cmd_type cmd_type,
786 struct wlan_objmgr_pdev *pdev,
787 struct wlan_objmgr_vdev *vdev,
788 enum wlan_serialization_node node_type)
789 {
790 qdf_list_node_t *cmd_node = NULL;
791 uint32_t queuelen;
792 qdf_list_node_t *nnode = NULL;
793 QDF_STATUS status;
794 bool node_found = 0;
795
796 queuelen = wlan_serialization_list_size(queue);
797
798 if (!queuelen)
799 goto error;
800
801 while (queuelen--) {
802 status = wlan_serialization_get_cmd_from_queue(queue, &nnode);
803 if (status != QDF_STATUS_SUCCESS)
804 break;
805
806 switch (match_type) {
807 case WLAN_SER_MATCH_PDEV:
808 if (wlan_serialization_match_cmd_pdev(
809 nnode, pdev, WLAN_SER_PDEV_NODE))
810 node_found = 1;
811 break;
812 case WLAN_SER_MATCH_VDEV:
813 if (wlan_serialization_match_cmd_vdev(
814 nnode, vdev, node_type))
815 node_found = 1;
816 break;
817 case WLAN_SER_MATCH_CMD_TYPE_VDEV:
818 if (wlan_serialization_match_cmd_type(
819 nnode, cmd_type, node_type) &&
820 wlan_serialization_match_cmd_vdev(
821 nnode, vdev, node_type))
822 node_found = 1;
823 break;
824 case WLAN_SER_MATCH_CMD_ID_VDEV:
825 if (wlan_serialization_match_cmd_id_type(
826 nnode, cmd, node_type) &&
827 wlan_serialization_match_cmd_vdev(
828 nnode, vdev, node_type))
829 node_found = 1;
830 break;
831 default:
832 break;
833 }
834
835 if (node_found) {
836 cmd_node = nnode;
837 break;
838 }
839 }
840 error:
841 return cmd_node;
842 }
843
844 QDF_STATUS
wlan_serialization_acquire_lock(qdf_spinlock_t * lock)845 wlan_serialization_acquire_lock(qdf_spinlock_t *lock)
846 {
847 qdf_spin_lock_bh(lock);
848
849 return QDF_STATUS_SUCCESS;
850 }
851
852 QDF_STATUS
wlan_serialization_release_lock(qdf_spinlock_t * lock)853 wlan_serialization_release_lock(qdf_spinlock_t *lock)
854 {
855 qdf_spin_unlock_bh(lock);
856
857 return QDF_STATUS_SUCCESS;
858 }
859
860 QDF_STATUS
wlan_serialization_create_lock(qdf_spinlock_t * lock)861 wlan_serialization_create_lock(qdf_spinlock_t *lock)
862 {
863 qdf_spinlock_create(lock);
864
865 return QDF_STATUS_SUCCESS;
866 }
867
868 QDF_STATUS
wlan_serialization_destroy_lock(qdf_spinlock_t * lock)869 wlan_serialization_destroy_lock(qdf_spinlock_t *lock)
870 {
871 qdf_spinlock_destroy(lock);
872
873 return QDF_STATUS_SUCCESS;
874 }
875
wlan_serialization_any_vdev_cmd_active(struct wlan_serialization_pdev_queue * pdev_queue)876 bool wlan_serialization_any_vdev_cmd_active(
877 struct wlan_serialization_pdev_queue *pdev_queue)
878 {
879 uint32_t vdev_bitmap_size;
880
881 vdev_bitmap_size =
882 (QDF_CHAR_BIT * sizeof(pdev_queue->vdev_active_cmd_bitmap));
883
884 return !qdf_bitmap_empty(pdev_queue->vdev_active_cmd_bitmap,
885 vdev_bitmap_size);
886 }
887