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