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 
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 
147 end:
148 	return cmd;
149 }
150 
151 struct wlan_serialization_command*
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*
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*
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