1 /*
2  * Copyright (c) 2017-2018 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 
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 != NULL)
47 			break;
48 	}
49 
50 	return pdev;
51 }
52 
53 static struct wlan_ser_pdev_obj *
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 
80 uint32_t wlan_serialization_get_active_list_count(
81 			struct wlan_objmgr_psoc *psoc,
82 			uint8_t is_cmd_from_active_scan_queue)
83 {
84 	struct wlan_ser_pdev_obj *ser_pdev_obj;
85 	qdf_list_t *queue;
86 	struct wlan_serialization_pdev_queue  *pdev_queue;
87 	uint32_t count;
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_active_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 
101 	wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock);
102 	queue = &pdev_queue->active_list;
103 	count = qdf_list_size(queue);
104 	wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
105 
106 	return count;
107 }
108 
109 uint32_t wlan_serialization_get_pending_list_count(
110 				struct wlan_objmgr_psoc *psoc,
111 				uint8_t is_cmd_from_pending_scan_queue)
112 {
113 	struct wlan_ser_pdev_obj *ser_pdev_obj;
114 	qdf_list_t *queue;
115 	uint32_t count = 0;
116 	struct wlan_serialization_pdev_queue  *pdev_queue;
117 
118 	ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc);
119 	if (!ser_pdev_obj) {
120 		ser_err("invalid ser_pdev_obj");
121 		return 0;
122 	}
123 
124 	if (is_cmd_from_pending_scan_queue)
125 		pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN];
126 	else
127 		pdev_queue =
128 		&ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN];
129 	queue = &pdev_queue->pending_list;
130 	wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock);
131 	count = qdf_list_size(queue);
132 	wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
133 
134 	return count;
135 }
136 
137 struct wlan_serialization_command*
138 wlan_serialization_peek_head_active_cmd_using_psoc(
139 			struct wlan_objmgr_psoc *psoc,
140 			uint8_t is_cmd_from_active_scan_queue)
141 {
142 	struct wlan_ser_pdev_obj *ser_pdev_obj;
143 	struct wlan_serialization_command_list *cmd_list = NULL;
144 	struct wlan_serialization_command *cmd = NULL;
145 	qdf_list_node_t *nnode = NULL;
146 	qdf_list_t *queue;
147 	struct wlan_serialization_pdev_queue  *pdev_queue;
148 
149 	ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc);
150 	if (!ser_pdev_obj) {
151 		ser_err("invalid ser_pdev_obj");
152 		return NULL;
153 	}
154 
155 	if (is_cmd_from_active_scan_queue)
156 		pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN];
157 	else
158 		pdev_queue =
159 		&ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN];
160 	queue = &pdev_queue->active_list;
161 	if (wlan_serialization_list_empty(queue)) {
162 		ser_err("Empty Queue");
163 		goto end;
164 	}
165 
166 	if (QDF_STATUS_SUCCESS != wlan_serialization_get_cmd_from_queue(queue,
167 						&nnode)) {
168 		ser_err("Can't get command from queue");
169 		goto end;
170 	}
171 
172 	cmd_list = qdf_container_of(nnode,
173 			struct wlan_serialization_command_list, pdev_node);
174 	cmd = &cmd_list->cmd;
175 	ser_debug("cmd_type[%d], cmd_id[%d]",
176 		  cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id);
177 
178 end:
179 	return cmd;
180 }
181 
182 struct wlan_serialization_command*
183 wlan_serialization_peek_head_pending_cmd_using_psoc(
184 			struct wlan_objmgr_psoc *psoc,
185 			uint8_t is_cmd_from_pending_scan_queue)
186 {
187 	struct wlan_ser_pdev_obj *ser_pdev_obj;
188 	struct wlan_serialization_command_list *cmd_list = NULL;
189 	struct wlan_serialization_command *cmd = NULL;
190 	qdf_list_node_t *nnode = NULL;
191 	qdf_list_t *queue;
192 	struct wlan_serialization_pdev_queue  *pdev_queue;
193 
194 	ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc);
195 	if (!ser_pdev_obj) {
196 		ser_err("invalid ser_pdev_obj");
197 		return NULL;
198 	}
199 	if (is_cmd_from_pending_scan_queue)
200 		pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN];
201 	else
202 		pdev_queue =
203 		&ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN];
204 	queue = &pdev_queue->pending_list;
205 	if (wlan_serialization_list_empty(queue)) {
206 		ser_err("Empty Queue");
207 		goto end;
208 	}
209 
210 	if (QDF_STATUS_SUCCESS != wlan_serialization_get_cmd_from_queue(
211 							queue,
212 							&nnode)) {
213 		ser_err("Can't get command from queue");
214 		goto end;
215 	}
216 	cmd_list = qdf_container_of(nnode,
217 			struct wlan_serialization_command_list, pdev_node);
218 	cmd = &cmd_list->cmd;
219 	ser_debug("cmd_type[%d] cmd_id[%d]matched",
220 		  cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id);
221 
222 end:
223 	return cmd;
224 }
225 
226 static struct wlan_serialization_command*
227 wlan_serialization_get_list_next_node(qdf_list_t *queue,
228 			struct wlan_serialization_command *cmd,
229 			struct wlan_ser_pdev_obj *ser_pdev_obj)
230 {
231 	struct wlan_serialization_command_list *cmd_list = NULL;
232 	qdf_list_node_t *pnode = NULL, *nnode = NULL;
233 	bool found = false;
234 	uint32_t i = 0;
235 	QDF_STATUS status;
236 	struct wlan_serialization_command *ret_cmd = NULL;
237 
238 	i = wlan_serialization_list_size(queue);
239 	if (i == 0) {
240 		ser_err("Empty Queue");
241 		return NULL;
242 	}
243 	while (i--) {
244 		if (!cmd_list)
245 			status = wlan_serialization_peek_front(queue, &nnode);
246 		else
247 			status = wlan_serialization_peek_next(queue, pnode,
248 							      &nnode);
249 
250 		if ((status != QDF_STATUS_SUCCESS) || found)
251 			break;
252 
253 		pnode = nnode;
254 		cmd_list = qdf_container_of(
255 					nnode,
256 					struct wlan_serialization_command_list,
257 					pdev_node);
258 		if (wlan_serialization_match_cmd_id_type(
259 				nnode, cmd, WLAN_SER_PDEV_NODE) &&
260 		    wlan_serialization_match_cmd_vdev(nnode,
261 						      cmd->vdev,
262 						      WLAN_SER_PDEV_NODE)) {
263 			found = true;
264 		}
265 		nnode = NULL;
266 	}
267 	if (nnode && found) {
268 		cmd_list = qdf_container_of(
269 				nnode,
270 				struct wlan_serialization_command_list,
271 				pdev_node);
272 		ret_cmd = &cmd_list->cmd;
273 	}
274 	if (!found) {
275 		ser_err("Can't locate next command");
276 		return NULL;
277 	}
278 	if (!nnode) {
279 		ser_debug("next node is empty, so fine");
280 		return NULL;
281 	}
282 
283 	return ret_cmd;
284 }
285 
286 struct wlan_serialization_command*
287 wlan_serialization_get_active_list_next_node_using_psoc(
288 			struct wlan_objmgr_psoc *psoc,
289 			struct wlan_serialization_command *prev_cmd,
290 			uint8_t is_cmd_for_active_scan_queue)
291 {
292 	struct wlan_ser_pdev_obj *ser_pdev_obj;
293 	qdf_list_t *queue;
294 	struct wlan_serialization_pdev_queue  *pdev_queue;
295 
296 	if (!prev_cmd) {
297 		ser_err("invalid prev_cmd");
298 		return NULL;
299 	}
300 
301 	ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc);
302 	if (!ser_pdev_obj) {
303 		ser_err("invalid ser_pdev_obj");
304 		return NULL;
305 	}
306 
307 	if (is_cmd_for_active_scan_queue)
308 		pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN];
309 	else
310 		pdev_queue =
311 		&ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN];
312 	queue = &pdev_queue->active_list;
313 	return wlan_serialization_get_list_next_node(queue, prev_cmd,
314 						     ser_pdev_obj);
315 }
316 
317 struct wlan_serialization_command*
318 wlan_serialization_get_pending_list_next_node_using_psoc(
319 			struct wlan_objmgr_psoc *psoc,
320 			struct wlan_serialization_command *prev_cmd,
321 			uint8_t is_cmd_for_pending_scan_queue)
322 {
323 	struct wlan_ser_pdev_obj *ser_pdev_obj;
324 	qdf_list_t *queue;
325 	struct wlan_serialization_pdev_queue  *pdev_queue;
326 
327 	if (!prev_cmd) {
328 		ser_err("invalid prev_cmd");
329 		return NULL;
330 	}
331 
332 	ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc);
333 	if (!ser_pdev_obj) {
334 		ser_err("invalid ser_pdev_obj");
335 		return NULL;
336 	}
337 	if (is_cmd_for_pending_scan_queue)
338 		pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN];
339 	else
340 		pdev_queue =
341 		&ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN];
342 	queue = &pdev_queue->pending_list;
343 	return wlan_serialization_get_list_next_node(queue, prev_cmd,
344 						     ser_pdev_obj);
345 }
346 
347 void wlan_serialization_purge_cmd_list_by_vdev_id(
348 			struct wlan_objmgr_psoc *psoc,
349 			uint8_t vdev_id, bool purge_scan_active_queue,
350 			bool purge_scan_pending_queue,
351 			bool purge_nonscan_active_queue,
352 			bool purge_nonscan_pending_queue,
353 			bool purge_all_queues)
354 {
355 	struct wlan_objmgr_vdev *vdev;
356 
357 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
358 			WLAN_SERIALIZATION_ID);
359 	if (!vdev) {
360 		ser_err("Invalid vdev");
361 		return;
362 	}
363 	wlan_serialization_purge_cmd_list(
364 				psoc, vdev, purge_scan_active_queue,
365 				purge_scan_pending_queue,
366 				purge_nonscan_active_queue,
367 				purge_nonscan_pending_queue,
368 				purge_all_queues);
369 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SERIALIZATION_ID);
370 }
371 
372 void wlan_serialization_purge_cmd_list(
373 		struct wlan_objmgr_psoc *psoc,
374 		struct wlan_objmgr_vdev *vdev,
375 		bool purge_scan_active_queue,
376 		bool purge_scan_pending_queue,
377 		bool purge_nonscan_active_queue,
378 		bool purge_nonscan_pending_queue,
379 		bool purge_all_queues)
380 {
381 	struct wlan_ser_pdev_obj *ser_pdev_obj;
382 	struct wlan_objmgr_pdev *pdev = NULL;
383 
384 	if (!psoc) {
385 		ser_err("Invalid psoc");
386 		return;
387 	}
388 	ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc);
389 	if (!ser_pdev_obj) {
390 		ser_err("Invalid ser_pdev_obj");
391 		return;
392 	}
393 
394 	pdev = wlan_serialization_get_first_pdev(psoc);
395 	if (!pdev) {
396 		ser_err("Invalid pdev");
397 		return;
398 	}
399 
400 	if (purge_all_queues || purge_scan_active_queue) {
401 		wlan_ser_cancel_scan_cmd(ser_pdev_obj,
402 					 pdev,
403 					 vdev,
404 					 NULL,
405 					 WLAN_SER_CMD_SCAN,
406 					 true);
407 	}
408 	if (purge_all_queues || purge_scan_pending_queue) {
409 		wlan_ser_cancel_scan_cmd(ser_pdev_obj,
410 					 pdev,
411 					 vdev,
412 					 NULL,
413 					 WLAN_SER_CMD_SCAN,
414 					 false);
415 	}
416 	if (purge_all_queues || purge_nonscan_active_queue) {
417 		wlan_ser_cancel_non_scan_cmd(
418 			ser_pdev_obj,
419 			pdev, vdev,
420 			NULL,
421 			WLAN_SER_CMD_NONSCAN,
422 			true);
423 	}
424 	if (purge_all_queues || purge_nonscan_pending_queue) {
425 		wlan_ser_cancel_non_scan_cmd(
426 			ser_pdev_obj,
427 			pdev, vdev,
428 			NULL,
429 			WLAN_SER_CMD_NONSCAN,
430 			false);
431 	}
432 	wlan_objmgr_pdev_release_ref(pdev, WLAN_SERIALIZATION_ID);
433 
434 	return;
435 }
436 
437