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