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