xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/serialization/src/wlan_serialization_api.c (revision 3149adf58a329e17232a4c0e58d460d025edd55a)
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_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 	return serialization_status;
264 }
265 
266 enum wlan_serialization_cmd_status
267 wlan_serialization_vdev_scan_status(struct wlan_objmgr_vdev *vdev)
268 {
269 	bool cmd_in_active, cmd_in_pending;
270 	struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev);
271 	struct wlan_serialization_pdev_priv_obj *ser_pdev_obj =
272 		wlan_serialization_get_pdev_priv_obj(pdev);
273 
274 	cmd_in_active =
275 	wlan_serialization_is_cmd_in_vdev_list(
276 			vdev, &ser_pdev_obj->active_scan_list);
277 
278 	cmd_in_pending =
279 	wlan_serialization_is_cmd_in_vdev_list(
280 			vdev, &ser_pdev_obj->pending_scan_list);
281 
282 	return wlan_serialization_is_cmd_in_active_pending(
283 			cmd_in_active, cmd_in_pending);
284 }
285 
286 void wlan_serialization_flush_cmd(
287 		struct wlan_serialization_queued_cmd_info *cmd)
288 {
289 	serialization_enter();
290 	if (!cmd) {
291 		serialization_err("cmd is null, can't flush");
292 		return;
293 	}
294 	/* TODO: discuss and fill this API later */
295 
296 	return;
297 }
298 
299 enum wlan_serialization_cmd_status
300 wlan_serialization_pdev_scan_status(struct wlan_objmgr_pdev *pdev)
301 {
302 	bool cmd_in_active, cmd_in_pending;
303 	struct wlan_serialization_pdev_priv_obj *ser_pdev_obj =
304 		wlan_serialization_get_pdev_priv_obj(pdev);
305 
306 	cmd_in_active =
307 	wlan_serialization_is_cmd_in_pdev_list(
308 			pdev, &ser_pdev_obj->active_scan_list);
309 
310 	cmd_in_pending =
311 	wlan_serialization_is_cmd_in_pdev_list(
312 			pdev, &ser_pdev_obj->pending_scan_list);
313 
314 	return wlan_serialization_is_cmd_in_active_pending(
315 			cmd_in_active, cmd_in_pending);
316 }
317 
318 struct wlan_serialization_command*
319 wlan_serialization_get_scan_cmd_using_scan_id(
320 		struct wlan_objmgr_psoc *psoc,
321 		uint8_t vdev_id, uint16_t scan_id,
322 		uint8_t is_scan_cmd_from_active_queue)
323 {
324 	uint32_t qlen;
325 	struct wlan_objmgr_vdev *vdev;
326 	struct wlan_objmgr_pdev *pdev;
327 	struct wlan_serialization_pdev_priv_obj *ser_pdev_obj;
328 	struct wlan_serialization_command_list *cmd_list = NULL;
329 	struct wlan_serialization_command *cmd = NULL;
330 	qdf_list_node_t *nnode = NULL;
331 	qdf_list_t *queue;
332 
333 	if (!psoc) {
334 		serialization_err("invalid psoc");
335 		return cmd;
336 	}
337 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
338 						WLAN_SERIALIZATION_ID);
339 	if (!vdev) {
340 		serialization_err("invalid vdev");
341 		return cmd;
342 	}
343 
344 	pdev = wlan_vdev_get_pdev(vdev);
345 	if (!pdev) {
346 		serialization_err("invalid pdev");
347 		goto release_vdev_ref;
348 	}
349 
350 	ser_pdev_obj = wlan_serialization_get_pdev_priv_obj(pdev);
351 	if (!ser_pdev_obj) {
352 		serialization_err("invalid ser_pdev_obj");
353 		goto release_vdev_ref;
354 	}
355 	if (is_scan_cmd_from_active_queue)
356 		queue = &ser_pdev_obj->active_scan_list;
357 	else
358 		queue = &ser_pdev_obj->pending_scan_list;
359 	qlen = qdf_list_size(queue);
360 	if (!qlen) {
361 		serialization_err("Empty Queue");
362 		goto release_vdev_ref;
363 	}
364 	while (qlen--) {
365 		if (QDF_STATUS_SUCCESS != wlan_serialization_get_cmd_from_queue(
366 							queue, &nnode)) {
367 			serialization_err("unsuccessful attempt");
368 			break;
369 		}
370 		cmd_list = qdf_container_of(nnode,
371 				struct wlan_serialization_command_list, node);
372 		if ((cmd_list->cmd.cmd_id == scan_id) &&
373 				(cmd_list->cmd.vdev == vdev)) {
374 			serialization_debug("cmd_id[%d] matched", scan_id);
375 			cmd = &cmd_list->cmd;
376 			break;
377 		}
378 	}
379 release_vdev_ref:
380 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SERIALIZATION_ID);
381 	return cmd;
382 }
383