xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_api.c (revision a175314c51a4ce5cec2835cc8a8c7dc0c1810915)
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_api.c
20  * This file provides an interface for the external components
21  * to utilize the services provided by the serialization
22  * component.
23  */
24 
25 /* Include files */
26 #include "wlan_objmgr_psoc_obj.h"
27 #include "wlan_objmgr_pdev_obj.h"
28 #include "wlan_objmgr_vdev_obj.h"
29 #include "wlan_serialization_main_i.h"
30 #include "wlan_serialization_utils_i.h"
31 
32 bool wlan_serialization_is_cmd_present_in_pending_queue(
33 		struct wlan_objmgr_psoc *psoc,
34 		struct wlan_serialization_command *cmd)
35 {
36 	if (!cmd) {
37 		serialization_err("invalid cmd");
38 		return false;
39 	}
40 	return wlan_serialization_is_cmd_present_queue(cmd, false);
41 }
42 
43 bool wlan_serialization_is_cmd_present_in_active_queue(
44 		struct wlan_objmgr_psoc *psoc,
45 		struct wlan_serialization_command *cmd)
46 {
47 	if (!cmd) {
48 		serialization_err("invalid cmd");
49 		return false;
50 	}
51 	return wlan_serialization_is_cmd_present_queue(cmd, true);
52 }
53 
54 QDF_STATUS
55 wlan_serialization_register_apply_rules_cb(struct wlan_objmgr_psoc *psoc,
56 		enum wlan_serialization_cmd_type cmd_type,
57 		wlan_serialization_apply_rules_cb cb)
58 {
59 	struct wlan_serialization_psoc_priv_obj *ser_soc_obj;
60 	QDF_STATUS status;
61 
62 	status = wlan_serialization_validate_cmdtype(cmd_type);
63 	if (status != QDF_STATUS_SUCCESS) {
64 		serialization_err("invalid cmd_type %d",
65 				cmd_type);
66 		return status;
67 	}
68 	ser_soc_obj = wlan_serialization_get_psoc_priv_obj(psoc);
69 	if (!ser_soc_obj) {
70 		serialization_err("invalid ser_soc_obj");
71 		return QDF_STATUS_E_FAILURE;
72 	}
73 	ser_soc_obj->apply_rules_cb[cmd_type] = cb;
74 
75 	return QDF_STATUS_SUCCESS;
76 }
77 
78 QDF_STATUS
79 wlan_serialization_deregister_apply_rules_cb(struct wlan_objmgr_psoc *psoc,
80 		enum wlan_serialization_cmd_type cmd_type)
81 {
82 	struct wlan_serialization_psoc_priv_obj *ser_soc_obj;
83 	QDF_STATUS status;
84 
85 	status = wlan_serialization_validate_cmdtype(cmd_type);
86 	if (status != QDF_STATUS_SUCCESS) {
87 		serialization_err("invalid cmd_type %d",
88 				cmd_type);
89 		return status;
90 	}
91 	ser_soc_obj = wlan_serialization_get_psoc_priv_obj(psoc);
92 	if (!ser_soc_obj) {
93 		serialization_err("invalid ser_soc_obj");
94 		return QDF_STATUS_E_FAILURE;
95 	}
96 	ser_soc_obj->apply_rules_cb[cmd_type] = NULL;
97 
98 	return QDF_STATUS_SUCCESS;
99 }
100 
101 QDF_STATUS
102 wlan_serialization_register_comp_info_cb(struct wlan_objmgr_psoc *psoc,
103 		enum wlan_umac_comp_id comp_id,
104 		enum wlan_serialization_cmd_type cmd_type,
105 		wlan_serialization_comp_info_cb cb)
106 {
107 	struct wlan_serialization_psoc_priv_obj *ser_soc_obj;
108 	QDF_STATUS status;
109 
110 	status = wlan_serialization_validate_cmd(comp_id, cmd_type);
111 	if (status != QDF_STATUS_SUCCESS) {
112 		serialization_err("invalid comp_id %d or cmd_type %d",
113 				comp_id, cmd_type);
114 		return status;
115 	}
116 	ser_soc_obj = wlan_serialization_get_psoc_priv_obj(psoc);
117 	if (!ser_soc_obj) {
118 		serialization_err("invalid ser_soc_obj");
119 		return QDF_STATUS_E_FAILURE;
120 	}
121 	ser_soc_obj->comp_info_cb[cmd_type][comp_id] = cb;
122 
123 	return QDF_STATUS_SUCCESS;
124 }
125 
126 QDF_STATUS
127 wlan_serialization_deregister_comp_info_cb(struct wlan_objmgr_psoc *psoc,
128 		enum wlan_umac_comp_id comp_id,
129 		enum wlan_serialization_cmd_type cmd_type)
130 {
131 	struct wlan_serialization_psoc_priv_obj *ser_soc_obj;
132 	QDF_STATUS status;
133 
134 	status = wlan_serialization_validate_cmd(comp_id, cmd_type);
135 	if (status != QDF_STATUS_SUCCESS) {
136 		serialization_err("invalid comp_id %d or cmd_type %d",
137 				comp_id, cmd_type);
138 		return status;
139 	}
140 	ser_soc_obj = wlan_serialization_get_psoc_priv_obj(psoc);
141 	if (!ser_soc_obj) {
142 		serialization_err("invalid ser_soc_obj");
143 		return QDF_STATUS_E_FAILURE;
144 	}
145 	ser_soc_obj->comp_info_cb[cmd_type][comp_id] = NULL;
146 
147 	return QDF_STATUS_SUCCESS;
148 }
149 
150 enum wlan_serialization_cmd_status
151 wlan_serialization_non_scan_cmd_status(struct wlan_objmgr_pdev *pdev,
152 		enum wlan_serialization_cmd_type cmd_id)
153 {
154 	serialization_enter();
155 
156 	return WLAN_SER_CMD_NOT_FOUND;
157 }
158 
159 enum wlan_serialization_cmd_status
160 wlan_serialization_cancel_request(
161 		struct wlan_serialization_queued_cmd_info *req)
162 {
163 	QDF_STATUS status;
164 
165 	serialization_enter();
166 	if (!req) {
167 		serialization_err("given request is empty");
168 		return WLAN_SER_CMD_NOT_FOUND;
169 	}
170 	status = wlan_serialization_validate_cmd(req->requestor, req->cmd_type);
171 	if (status != QDF_STATUS_SUCCESS) {
172 		serialization_err("req is not valid");
173 		return WLAN_SER_CMD_NOT_FOUND;
174 	}
175 
176 	return wlan_serialization_find_and_cancel_cmd(req);
177 }
178 
179 void wlan_serialization_remove_cmd(
180 		struct wlan_serialization_queued_cmd_info *cmd)
181 {
182 	QDF_STATUS status;
183 
184 	serialization_enter();
185 	if (!cmd) {
186 		serialization_err("given request is empty");
187 		QDF_ASSERT(0);
188 		return;
189 	}
190 	status = wlan_serialization_validate_cmd(cmd->requestor, cmd->cmd_type);
191 	if (status != QDF_STATUS_SUCCESS) {
192 		serialization_err("cmd is not valid");
193 		QDF_ASSERT(0);
194 		return;
195 	}
196 	wlan_serialization_find_and_remove_cmd(cmd);
197 
198 	return;
199 }
200 
201 enum wlan_serialization_status
202 wlan_serialization_request(struct wlan_serialization_command *cmd)
203 {
204 	bool is_active_cmd_allowed;
205 	QDF_STATUS status;
206 	enum wlan_serialization_status serialization_status;
207 	uint8_t comp_id;
208 	struct wlan_serialization_psoc_priv_obj *ser_soc_obj;
209 	union wlan_serialization_rules_info info;
210 	struct wlan_serialization_pdev_priv_obj *ser_pdev_obj = NULL;
211 	struct wlan_objmgr_pdev *pdev = NULL;
212 	struct wlan_serialization_command_list *cmd_list = NULL;
213 
214 	serialization_enter();
215 	if (!cmd) {
216 		serialization_err("serialization cmd is null");
217 		return WLAN_SER_CMD_DENIED_UNSPECIFIED;
218 	}
219 	status = wlan_serialization_validate_cmd(cmd->source, cmd->cmd_type);
220 	if (status != QDF_STATUS_SUCCESS) {
221 		serialization_err("cmd is not valid");
222 		return WLAN_SER_CMD_DENIED_UNSPECIFIED;
223 	}
224 
225 	ser_soc_obj = wlan_serialization_get_psoc_obj(cmd);
226 	if (!ser_soc_obj) {
227 		serialization_err("ser_soc_obj is invalid");
228 		return WLAN_SER_CMD_DENIED_UNSPECIFIED;
229 	}
230 
231 	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
232 	if (!pdev) {
233 		serialization_err("pdev is invalid");
234 		return WLAN_SER_CMD_DENIED_UNSPECIFIED;
235 	}
236 
237 	ser_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
238 			WLAN_UMAC_COMP_SERIALIZATION);
239 	if (!ser_pdev_obj) {
240 		serialization_err("Invalid ser_pdev_obj");
241 		return WLAN_SER_CMD_DENIED_UNSPECIFIED;
242 	}
243 	/*
244 	 * Get Component Info callback by calling
245 	 * each registered module
246 	 */
247 	for (comp_id = 0; comp_id < WLAN_UMAC_COMP_ID_MAX; comp_id++) {
248 		if (!ser_soc_obj->comp_info_cb[cmd->cmd_type][comp_id])
249 			continue;
250 		(ser_soc_obj->comp_info_cb[cmd->cmd_type][comp_id])(cmd->vdev,
251 			&info);
252 		if (!ser_soc_obj->apply_rules_cb[cmd->cmd_type])
253 			continue;
254 		if (!ser_soc_obj->apply_rules_cb[cmd->cmd_type](&info, comp_id))
255 			return WLAN_SER_CMD_DENIED_RULES_FAILED;
256 	}
257 
258 	is_active_cmd_allowed = wlan_serialization_is_active_cmd_allowed(cmd);
259 	serialization_status = wlan_serialization_enqueue_cmd(
260 				cmd, is_active_cmd_allowed, &cmd_list);
261 	if (WLAN_SER_CMD_ACTIVE == serialization_status)
262 		wlan_serialization_activate_cmd(cmd_list, ser_pdev_obj);
263 
264 	return serialization_status;
265 }
266 
267 enum wlan_serialization_cmd_status
268 wlan_serialization_vdev_scan_status(struct wlan_objmgr_vdev *vdev)
269 {
270 	bool cmd_in_active, cmd_in_pending;
271 	struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev);
272 	struct wlan_serialization_pdev_priv_obj *ser_pdev_obj =
273 		wlan_serialization_get_pdev_priv_obj(pdev);
274 
275 	cmd_in_active =
276 	wlan_serialization_is_cmd_in_vdev_list(
277 			vdev, &ser_pdev_obj->active_scan_list);
278 
279 	cmd_in_pending =
280 	wlan_serialization_is_cmd_in_vdev_list(
281 			vdev, &ser_pdev_obj->pending_scan_list);
282 
283 	return wlan_serialization_is_cmd_in_active_pending(
284 			cmd_in_active, cmd_in_pending);
285 }
286 
287 void wlan_serialization_flush_cmd(
288 		struct wlan_serialization_queued_cmd_info *cmd)
289 {
290 	serialization_enter();
291 	if (!cmd) {
292 		serialization_err("cmd is null, can't flush");
293 		return;
294 	}
295 	/* TODO: discuss and fill this API later */
296 
297 	return;
298 }
299 
300 enum wlan_serialization_cmd_status
301 wlan_serialization_pdev_scan_status(struct wlan_objmgr_pdev *pdev)
302 {
303 	bool cmd_in_active, cmd_in_pending;
304 	struct wlan_serialization_pdev_priv_obj *ser_pdev_obj =
305 		wlan_serialization_get_pdev_priv_obj(pdev);
306 
307 	cmd_in_active = !qdf_list_empty(&ser_pdev_obj->active_scan_list);
308 	cmd_in_pending = !qdf_list_empty(&ser_pdev_obj->pending_scan_list);
309 
310 	return wlan_serialization_is_cmd_in_active_pending(
311 			cmd_in_active, cmd_in_pending);
312 }
313 
314 struct wlan_serialization_command*
315 wlan_serialization_get_scan_cmd_using_scan_id(
316 		struct wlan_objmgr_psoc *psoc,
317 		uint8_t vdev_id, uint16_t scan_id,
318 		uint8_t is_scan_cmd_from_active_queue)
319 {
320 	uint32_t qlen;
321 	struct wlan_objmgr_vdev *vdev;
322 	struct wlan_objmgr_pdev *pdev;
323 	struct wlan_serialization_pdev_priv_obj *ser_pdev_obj;
324 	struct wlan_serialization_command *cmd = NULL;
325 	qdf_list_node_t *nnode = NULL;
326 	qdf_list_t *queue;
327 
328 	if (!psoc) {
329 		serialization_err("invalid psoc");
330 		return cmd;
331 	}
332 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
333 						WLAN_SERIALIZATION_ID);
334 	if (!vdev) {
335 		serialization_err("invalid vdev");
336 		return cmd;
337 	}
338 
339 	pdev = wlan_vdev_get_pdev(vdev);
340 	if (!pdev) {
341 		serialization_err("invalid pdev");
342 		goto release_vdev_ref;
343 	}
344 
345 	ser_pdev_obj = wlan_serialization_get_pdev_priv_obj(pdev);
346 	if (!ser_pdev_obj) {
347 		serialization_err("invalid ser_pdev_obj");
348 		goto release_vdev_ref;
349 	}
350 	if (is_scan_cmd_from_active_queue)
351 		queue = &ser_pdev_obj->active_scan_list;
352 	else
353 		queue = &ser_pdev_obj->pending_scan_list;
354 	qlen = wlan_serialization_list_size(queue, ser_pdev_obj);
355 	while (qlen--) {
356 		if (QDF_STATUS_SUCCESS != wlan_serialization_get_cmd_from_queue(
357 						queue, &nnode, ser_pdev_obj)) {
358 			serialization_debug("Node not found");
359 			break;
360 		}
361 		if (wlan_serialization_match_cmd_scan_id(nnode, &cmd, scan_id,
362 							 vdev, ser_pdev_obj)) {
363 			serialization_debug("Cmd matched with the scan_id");
364 			break;
365 		}
366 	}
367 release_vdev_ref:
368 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SERIALIZATION_ID);
369 
370 	return cmd;
371 }
372 
373 void *wlan_serialization_get_active_cmd(struct wlan_objmgr_psoc *psoc,
374 				      uint8_t vdev_id,
375 				      enum wlan_serialization_cmd_type cmd_type)
376 {
377 	uint32_t qlen;
378 	struct wlan_objmgr_vdev *vdev;
379 	struct wlan_objmgr_pdev *pdev;
380 	struct wlan_serialization_pdev_priv_obj *ser_pdev_obj;
381 	struct wlan_serialization_command_list *cmd_list = NULL;
382 	void *umac_cmd = NULL;
383 	qdf_list_node_t *nnode = NULL;
384 	qdf_list_t *queue;
385 
386 	if (!psoc) {
387 		serialization_err("invalid psoc");
388 		return umac_cmd;
389 	}
390 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
391 						    WLAN_SERIALIZATION_ID);
392 	if (!vdev) {
393 		serialization_err("invalid vdev");
394 		return umac_cmd;
395 	}
396 
397 	pdev = wlan_vdev_get_pdev(vdev);
398 	if (!pdev) {
399 		serialization_err("invalid pdev");
400 		goto release_vdev_ref;
401 	}
402 
403 	ser_pdev_obj = wlan_serialization_get_pdev_priv_obj(pdev);
404 	if (!ser_pdev_obj) {
405 		serialization_err("invalid ser_pdev_obj");
406 		goto release_vdev_ref;
407 	}
408 
409 	queue = &ser_pdev_obj->active_list;
410 
411 	qlen = qdf_list_size(queue);
412 	if (!qlen) {
413 		serialization_err("Empty Queue");
414 		goto release_vdev_ref;
415 	}
416 	while (qlen--) {
417 		if (QDF_STATUS_SUCCESS != wlan_serialization_get_cmd_from_queue(
418 							queue, &nnode,
419 							ser_pdev_obj)) {
420 			serialization_err("unsuccessful attempt");
421 			break;
422 		}
423 		cmd_list = qdf_container_of(nnode,
424 					 struct wlan_serialization_command_list,
425 					 node);
426 		if (cmd_list->cmd.cmd_type == cmd_type &&
427 		    cmd_list->cmd.vdev == vdev) {
428 			serialization_debug("cmd_type[%d] matched", cmd_type);
429 			umac_cmd = cmd_list->cmd.umac_cmd;
430 			break;
431 		}
432 	}
433 release_vdev_ref:
434 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SERIALIZATION_ID);
435 
436 	return umac_cmd;
437 }
438