1 /*
2 * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
7 * copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18 /**
19 * DOC: wlan_serialization_legacy_api.c
20 * This file provides prototypes of the routines needed for the
21 * legacy mcl serialization to utilize the services provided by the
22 * serialization component.
23 */
24
25 #include "wlan_serialization_legacy_api.h"
26 #include "wlan_serialization_main_i.h"
27 #include "wlan_serialization_utils_i.h"
28 #include "wlan_objmgr_vdev_obj.h"
29 #include "wlan_serialization_internal_i.h"
30 #include "wlan_serialization_scan_i.h"
31 #include "wlan_serialization_non_scan_i.h"
32
wlan_serialization_get_first_pdev(struct wlan_objmgr_psoc * psoc)33 static struct wlan_objmgr_pdev *wlan_serialization_get_first_pdev(
34 struct wlan_objmgr_psoc *psoc)
35 {
36 struct wlan_objmgr_pdev *pdev;
37 uint8_t i = 0;
38
39 if (!psoc) {
40 ser_err("invalid psoc");
41 return NULL;
42 }
43 for (i = 0; i < WLAN_UMAC_MAX_PDEVS; i++) {
44 pdev = wlan_objmgr_get_pdev_by_id(psoc, i,
45 WLAN_SERIALIZATION_ID);
46 if (pdev)
47 break;
48 }
49
50 return pdev;
51 }
52
53 static struct wlan_ser_pdev_obj *
wlan_serialization_get_pdev_priv_obj_using_psoc(struct wlan_objmgr_psoc * psoc)54 wlan_serialization_get_pdev_priv_obj_using_psoc(struct wlan_objmgr_psoc *psoc)
55 {
56 struct wlan_objmgr_pdev *pdev = NULL;
57 struct wlan_ser_pdev_obj *ser_pdev_obj;
58
59 if (!psoc) {
60 ser_err("invalid psoc");
61 return NULL;
62 }
63
64 pdev = wlan_serialization_get_first_pdev(psoc);
65 if (!pdev) {
66 ser_err("invalid pdev");
67 return NULL;
68 }
69
70 ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev);
71 wlan_objmgr_pdev_release_ref(pdev, WLAN_SERIALIZATION_ID);
72 if (!ser_pdev_obj) {
73 ser_err("invalid ser_pdev_obj");
74 return NULL;
75 }
76
77 return ser_pdev_obj;
78 }
79
wlan_serialization_get_pending_list_count(struct wlan_objmgr_psoc * psoc,uint8_t is_cmd_from_pending_scan_queue)80 uint32_t wlan_serialization_get_pending_list_count(
81 struct wlan_objmgr_psoc *psoc,
82 uint8_t is_cmd_from_pending_scan_queue)
83 {
84 struct wlan_ser_pdev_obj *ser_pdev_obj;
85 qdf_list_t *queue;
86 uint32_t count = 0;
87 struct wlan_serialization_pdev_queue *pdev_queue;
88
89 ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc);
90 if (!ser_pdev_obj) {
91 ser_err("invalid ser_pdev_obj");
92 return 0;
93 }
94
95 if (is_cmd_from_pending_scan_queue)
96 pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN];
97 else
98 pdev_queue =
99 &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN];
100 queue = &pdev_queue->pending_list;
101 wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock);
102 count = qdf_list_size(queue);
103 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
104
105 return count;
106 }
107
108 struct wlan_serialization_command*
wlan_serialization_peek_head_active_cmd_using_psoc(struct wlan_objmgr_psoc * psoc,uint8_t is_cmd_from_active_scan_queue)109 wlan_serialization_peek_head_active_cmd_using_psoc(
110 struct wlan_objmgr_psoc *psoc,
111 uint8_t is_cmd_from_active_scan_queue)
112 {
113 struct wlan_ser_pdev_obj *ser_pdev_obj;
114 struct wlan_serialization_command_list *cmd_list = NULL;
115 struct wlan_serialization_command *cmd = NULL;
116 qdf_list_node_t *nnode = NULL;
117 qdf_list_t *queue;
118 struct wlan_serialization_pdev_queue *pdev_queue;
119
120 ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc);
121 if (!ser_pdev_obj) {
122 ser_err("invalid ser_pdev_obj");
123 return NULL;
124 }
125
126 if (is_cmd_from_active_scan_queue)
127 pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN];
128 else
129 pdev_queue =
130 &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN];
131 queue = &pdev_queue->active_list;
132 if (wlan_serialization_list_empty(queue)) {
133 ser_debug_rl("Empty Queue");
134 goto end;
135 }
136
137 if (QDF_STATUS_SUCCESS != wlan_serialization_get_cmd_from_queue(queue,
138 &nnode)) {
139 ser_err("Can't get command from queue");
140 goto end;
141 }
142
143 cmd_list = qdf_container_of(nnode,
144 struct wlan_serialization_command_list, pdev_node);
145 cmd = &cmd_list->cmd;
146
147 end:
148 return cmd;
149 }
150
151 struct wlan_serialization_command*
wlan_serialization_peek_head_pending_cmd_using_psoc(struct wlan_objmgr_psoc * psoc,uint8_t is_cmd_from_pending_scan_queue)152 wlan_serialization_peek_head_pending_cmd_using_psoc(
153 struct wlan_objmgr_psoc *psoc,
154 uint8_t is_cmd_from_pending_scan_queue)
155 {
156 struct wlan_ser_pdev_obj *ser_pdev_obj;
157 struct wlan_serialization_command_list *cmd_list = NULL;
158 struct wlan_serialization_command *cmd = NULL;
159 qdf_list_node_t *nnode = NULL;
160 qdf_list_t *queue;
161 struct wlan_serialization_pdev_queue *pdev_queue;
162
163 ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc);
164 if (!ser_pdev_obj) {
165 ser_err("invalid ser_pdev_obj");
166 return NULL;
167 }
168 if (is_cmd_from_pending_scan_queue)
169 pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN];
170 else
171 pdev_queue =
172 &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN];
173 queue = &pdev_queue->pending_list;
174 if (wlan_serialization_list_empty(queue))
175 goto end;
176
177 wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock);
178 if (QDF_STATUS_SUCCESS != wlan_serialization_get_cmd_from_queue(
179 queue,
180 &nnode)) {
181 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
182 ser_err("Can't get command from queue");
183 goto end;
184 }
185 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
186 cmd_list = qdf_container_of(nnode,
187 struct wlan_serialization_command_list, pdev_node);
188 cmd = &cmd_list->cmd;
189 ser_debug("cmd_type[%d] cmd_id[%d]matched",
190 cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id);
191
192 end:
193 return cmd;
194 }
195
196 static struct wlan_serialization_command*
wlan_serialization_get_list_next_node(qdf_list_t * queue,struct wlan_serialization_command * cmd,struct wlan_ser_pdev_obj * ser_pdev_obj)197 wlan_serialization_get_list_next_node(qdf_list_t *queue,
198 struct wlan_serialization_command *cmd,
199 struct wlan_ser_pdev_obj *ser_pdev_obj)
200 {
201 struct wlan_serialization_command_list *cmd_list = NULL;
202 qdf_list_node_t *pnode = NULL, *nnode = NULL;
203 bool found = false;
204 uint32_t i = 0;
205 QDF_STATUS status;
206 struct wlan_serialization_command *ret_cmd = NULL;
207
208 i = wlan_serialization_list_size(queue);
209 if (i == 0) {
210 ser_err("Empty Queue");
211 return NULL;
212 }
213 while (i--) {
214 if (!cmd_list)
215 status = wlan_serialization_peek_front(queue, &nnode);
216 else
217 status = wlan_serialization_peek_next(queue, pnode,
218 &nnode);
219
220 if ((status != QDF_STATUS_SUCCESS) || found)
221 break;
222
223 pnode = nnode;
224 cmd_list = qdf_container_of(
225 nnode,
226 struct wlan_serialization_command_list,
227 pdev_node);
228 if (wlan_serialization_match_cmd_id_type(
229 nnode, cmd, WLAN_SER_PDEV_NODE) &&
230 wlan_serialization_match_cmd_vdev(nnode,
231 cmd->vdev,
232 WLAN_SER_PDEV_NODE)) {
233 found = true;
234 }
235 nnode = NULL;
236 }
237 if (nnode && found) {
238 cmd_list = qdf_container_of(
239 nnode,
240 struct wlan_serialization_command_list,
241 pdev_node);
242 ret_cmd = &cmd_list->cmd;
243 }
244 if (!found) {
245 ser_err("Can't locate next command");
246 return NULL;
247 }
248 if (!nnode) {
249 ser_debug("next node is empty, so fine");
250 return NULL;
251 }
252
253 return ret_cmd;
254 }
255
256 struct wlan_serialization_command*
wlan_serialization_get_pending_list_next_node_using_psoc(struct wlan_objmgr_psoc * psoc,struct wlan_serialization_command * prev_cmd,uint8_t is_cmd_for_pending_scan_queue)257 wlan_serialization_get_pending_list_next_node_using_psoc(
258 struct wlan_objmgr_psoc *psoc,
259 struct wlan_serialization_command *prev_cmd,
260 uint8_t is_cmd_for_pending_scan_queue)
261 {
262 struct wlan_ser_pdev_obj *ser_pdev_obj;
263 qdf_list_t *queue;
264 struct wlan_serialization_pdev_queue *pdev_queue;
265 struct wlan_serialization_command *cmd;
266
267 if (!prev_cmd) {
268 ser_err("invalid prev_cmd");
269 return NULL;
270 }
271
272 ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc);
273 if (!ser_pdev_obj) {
274 ser_err("invalid ser_pdev_obj");
275 return NULL;
276 }
277 if (is_cmd_for_pending_scan_queue)
278 pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN];
279 else
280 pdev_queue =
281 &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN];
282 queue = &pdev_queue->pending_list;
283
284 wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock);
285 cmd = wlan_serialization_get_list_next_node(queue, prev_cmd,
286 ser_pdev_obj);
287 wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
288
289 return cmd;
290 }
291