1 /*
2  * Copyright (c) 2017-2019 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)
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_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*
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 	ser_debug("cmd_type[%d], cmd_id[%d]",
147 		  cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id);
148 
149 end:
150 	return cmd;
151 }
152 
153 struct wlan_serialization_command*
154 wlan_serialization_peek_head_pending_cmd_using_psoc(
155 			struct wlan_objmgr_psoc *psoc,
156 			uint8_t is_cmd_from_pending_scan_queue)
157 {
158 	struct wlan_ser_pdev_obj *ser_pdev_obj;
159 	struct wlan_serialization_command_list *cmd_list = NULL;
160 	struct wlan_serialization_command *cmd = NULL;
161 	qdf_list_node_t *nnode = NULL;
162 	qdf_list_t *queue;
163 	struct wlan_serialization_pdev_queue  *pdev_queue;
164 
165 	ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc);
166 	if (!ser_pdev_obj) {
167 		ser_err("invalid ser_pdev_obj");
168 		return NULL;
169 	}
170 	if (is_cmd_from_pending_scan_queue)
171 		pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN];
172 	else
173 		pdev_queue =
174 		&ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN];
175 	queue = &pdev_queue->pending_list;
176 	if (wlan_serialization_list_empty(queue)) {
177 		ser_err("Empty Queue");
178 		goto end;
179 	}
180 
181 	wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock);
182 	if (QDF_STATUS_SUCCESS != wlan_serialization_get_cmd_from_queue(
183 							queue,
184 							&nnode)) {
185 		wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
186 		ser_err("Can't get command from queue");
187 		goto end;
188 	}
189 	wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
190 	cmd_list = qdf_container_of(nnode,
191 			struct wlan_serialization_command_list, pdev_node);
192 	cmd = &cmd_list->cmd;
193 	ser_debug("cmd_type[%d] cmd_id[%d]matched",
194 		  cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id);
195 
196 end:
197 	return cmd;
198 }
199 
200 static struct wlan_serialization_command*
201 wlan_serialization_get_list_next_node(qdf_list_t *queue,
202 			struct wlan_serialization_command *cmd,
203 			struct wlan_ser_pdev_obj *ser_pdev_obj)
204 {
205 	struct wlan_serialization_command_list *cmd_list = NULL;
206 	qdf_list_node_t *pnode = NULL, *nnode = NULL;
207 	bool found = false;
208 	uint32_t i = 0;
209 	QDF_STATUS status;
210 	struct wlan_serialization_command *ret_cmd = NULL;
211 
212 	i = wlan_serialization_list_size(queue);
213 	if (i == 0) {
214 		ser_err("Empty Queue");
215 		return NULL;
216 	}
217 	while (i--) {
218 		if (!cmd_list)
219 			status = wlan_serialization_peek_front(queue, &nnode);
220 		else
221 			status = wlan_serialization_peek_next(queue, pnode,
222 							      &nnode);
223 
224 		if ((status != QDF_STATUS_SUCCESS) || found)
225 			break;
226 
227 		pnode = nnode;
228 		cmd_list = qdf_container_of(
229 					nnode,
230 					struct wlan_serialization_command_list,
231 					pdev_node);
232 		if (wlan_serialization_match_cmd_id_type(
233 				nnode, cmd, WLAN_SER_PDEV_NODE) &&
234 		    wlan_serialization_match_cmd_vdev(nnode,
235 						      cmd->vdev,
236 						      WLAN_SER_PDEV_NODE)) {
237 			found = true;
238 		}
239 		nnode = NULL;
240 	}
241 	if (nnode && found) {
242 		cmd_list = qdf_container_of(
243 				nnode,
244 				struct wlan_serialization_command_list,
245 				pdev_node);
246 		ret_cmd = &cmd_list->cmd;
247 	}
248 	if (!found) {
249 		ser_err("Can't locate next command");
250 		return NULL;
251 	}
252 	if (!nnode) {
253 		ser_debug("next node is empty, so fine");
254 		return NULL;
255 	}
256 
257 	return ret_cmd;
258 }
259 
260 struct wlan_serialization_command*
261 wlan_serialization_get_pending_list_next_node_using_psoc(
262 			struct wlan_objmgr_psoc *psoc,
263 			struct wlan_serialization_command *prev_cmd,
264 			uint8_t is_cmd_for_pending_scan_queue)
265 {
266 	struct wlan_ser_pdev_obj *ser_pdev_obj;
267 	qdf_list_t *queue;
268 	struct wlan_serialization_pdev_queue  *pdev_queue;
269 	struct wlan_serialization_command *cmd;
270 
271 	if (!prev_cmd) {
272 		ser_err("invalid prev_cmd");
273 		return NULL;
274 	}
275 
276 	ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc);
277 	if (!ser_pdev_obj) {
278 		ser_err("invalid ser_pdev_obj");
279 		return NULL;
280 	}
281 	if (is_cmd_for_pending_scan_queue)
282 		pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN];
283 	else
284 		pdev_queue =
285 		&ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN];
286 	queue = &pdev_queue->pending_list;
287 
288 	wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock);
289 	cmd = wlan_serialization_get_list_next_node(queue, prev_cmd,
290 						    ser_pdev_obj);
291 	wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
292 
293 	return cmd;
294 }
295