xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlme/mlme_utils/wlan_vdev_mlme_ser_if.c (revision 1f55ed1a9f5050d8da228aa8dd3fff7c0242aa71)
1 /*
2  * Copyright (c) 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 /**
20  * @file wlan_vdev_mlme_ser.c
21  * This file contains the APIs to support interface between vdev_mlme and
22  * serialization module
23  */
24 
25 #include <qdf_types.h>
26 #include <qdf_status.h>
27 #include <qdf_mem.h>
28 #include <wlan_serialization_api.h>
29 #include <wlan_objmgr_vdev_obj.h>
30 #include <wlan_cmn.h>
31 #include <wlan_mlme_dbg.h>
32 #include <include/wlan_vdev_mlme.h>
33 #include <wlan_vdev_mlme_api.h>
34 #include <wlan_vdev_mlme_ser_if.h>
35 
36 enum wlan_serialization_status
37 wlan_vdev_mlme_ser_start_bss(struct wlan_serialization_command *cmd)
38 {
39 	struct vdev_mlme_obj *vdev_mlme;
40 
41 	if (!cmd || !cmd->vdev) {
42 		mlme_err("Null input");
43 		return WLAN_SER_CMD_DENIED_UNSPECIFIED;
44 	}
45 
46 	/*
47 	 * Serialization command filtering logic
48 	 * a. Cancel any existing start bss cmd in the pending queue
49 	 * b. If there is an start bss cmd in active queue and
50 	 * there is no stop bss cmd in pending queue,
51 	 * then explicitly enqueue a stop bss cmd to avoid back to
52 	 * back execution of UP cmd.
53 	 * c. Enqueue the new start bss cmd with serialization
54 	 */
55 	wlan_vdev_mlme_ser_cancel_request(
56 			cmd->vdev,
57 			WLAN_SER_CMD_VDEV_START_BSS,
58 			WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE);
59 
60 	if (wlan_serialization_is_cmd_present_in_active_queue(NULL, cmd)) {
61 		vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(cmd->vdev);
62 		if (mlme_vdev_enqueue_exp_ser_cmd(vdev_mlme,
63 						  WLAN_SER_CMD_VDEV_STOP_BSS)) {
64 			mlme_err("Unable to add the exception cmd request");
65 			return WLAN_SER_CMD_DENIED_UNSPECIFIED;
66 		}
67 	}
68 
69 	return wlan_serialization_request(cmd);
70 }
71 
72 enum wlan_serialization_status
73 wlan_vdev_mlme_ser_stop_bss(struct wlan_serialization_command *cmd)
74 {
75 	uint8_t stop_cmd_pending;
76 	uint8_t ret;
77 
78 	if (!cmd || !cmd->vdev) {
79 		mlme_err("Null input");
80 		return WLAN_SER_CMD_DENIED_UNSPECIFIED;
81 	}
82 	/*
83 	 * Serialization command filtering logic
84 	 * a. Cancel any existing start/stop/restart command in the pending
85 	 *  queue.
86 	 * b. If there is a stop cmd in active queue then return
87 	 * c. Else enqueue the cmd
88 	 * d. If stop cmd already existed in pending queue then return with
89 	 *  already exists else return the enqueued return value.
90 	 */
91 	stop_cmd_pending =
92 		wlan_serialization_is_cmd_present_in_pending_queue(NULL, cmd);
93 	wlan_vdev_mlme_ser_cancel_request(cmd->vdev,
94 					  WLAN_SER_CMD_NONSCAN,
95 					  WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD);
96 
97 	if (wlan_serialization_is_cmd_present_in_active_queue(NULL, cmd)) {
98 		mlme_err("Cmd already exist in the active queue");
99 		return WLAN_SER_CMD_DENIED_UNSPECIFIED;
100 	}
101 
102 	ret = wlan_serialization_request(cmd);
103 
104 	if (stop_cmd_pending && ret == WLAN_SER_CMD_PENDING)
105 		return WLAN_SER_CMD_ALREADY_EXISTS;
106 	else
107 		return ret;
108 }
109 
110 enum wlan_serialization_status
111 wlan_vdev_mlme_ser_restart_bss(struct wlan_serialization_command *cmd)
112 {
113 	if (!cmd || !cmd->vdev) {
114 		mlme_err("Null input");
115 		return WLAN_SER_CMD_DENIED_UNSPECIFIED;
116 	}
117 	/*
118 	 * Serialization command filtering logic
119 	 * a. Cancel any existing RESTART cmd in the pending queue
120 	 * b. Enqueue the new RESTART cmd
121 	 */
122 	wlan_vdev_mlme_ser_cancel_request(
123 			cmd->vdev,
124 			WLAN_SER_CMD_VDEV_RESTART,
125 			WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE);
126 	return wlan_serialization_request(cmd);
127 }
128 
129 enum wlan_serialization_status
130 wlan_vdev_mlme_ser_connect(struct wlan_serialization_command *cmd)
131 {
132 	struct vdev_mlme_obj *vdev_mlme;
133 
134 	if (!cmd || !cmd->vdev) {
135 		mlme_err("Null input");
136 		return WLAN_SER_CMD_DENIED_UNSPECIFIED;
137 	}
138 	/*
139 	 * Serialization command filtering logic
140 	 * a. Cancel any existing CONNECT cmd in the pending queue
141 	 * b. If there is an CONNECT cmd in active queue and there is no
142 	 * DISCONNECT cmd in pending queue, then explicitly enqueue a
143 	 * DISCONNECT cmd to avoid back to back execution of CONNECT cmd.
144 	 * c. Enqueue the new CONNECT cmd to the pending queue
145 	 */
146 	wlan_vdev_mlme_ser_cancel_request(
147 			cmd->vdev,
148 			WLAN_SER_CMD_VDEV_CONNECT,
149 			WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE);
150 
151 	if (wlan_serialization_is_cmd_present_in_active_queue(NULL, cmd)) {
152 		vdev_mlme = wlan_objmgr_vdev_get_comp_private_obj(
153 				cmd->vdev, WLAN_UMAC_COMP_MLME);
154 		if (mlme_vdev_enqueue_exp_ser_cmd(vdev_mlme,
155 					WLAN_SER_CMD_VDEV_DISCONNECT)) {
156 			mlme_err("Unable to add the exception cmd request");
157 			return WLAN_SER_CMD_DENIED_UNSPECIFIED;
158 		}
159 	}
160 
161 	return wlan_serialization_request(cmd);
162 }
163 
164 enum wlan_serialization_status
165 wlan_vdev_mlme_ser_disconnect(struct wlan_serialization_command *cmd)
166 {
167 	if (!cmd || !cmd->vdev) {
168 		mlme_err("Null input");
169 		return WLAN_SER_CMD_DENIED_UNSPECIFIED;
170 	}
171 	/*
172 	 * Serialization command filtering logic
173 	 * a.Cancel any existing CONNECT/DISCONNECT/RESTART command in the
174 	 * pending queue
175 	 * b.If there is a DISCONNECT cmd in active queue then return
176 	 * c.Else enqueue the DISCONNECT cmd
177 	 */
178 	wlan_vdev_mlme_ser_cancel_request(cmd->vdev,
179 					  WLAN_SER_CMD_NONSCAN,
180 					  WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD);
181 
182 	if (wlan_serialization_is_cmd_present_in_active_queue(NULL, cmd)) {
183 		mlme_err("Cmd already exist in the active queue");
184 		return WLAN_SER_CMD_DENIED_UNSPECIFIED;
185 	}
186 
187 	return wlan_serialization_request(cmd);
188 }
189 
190 void
191 wlan_vdev_mlme_ser_remove_request(struct wlan_objmgr_vdev *vdev,
192 				  uint32_t cmd_id,
193 				  enum wlan_serialization_cmd_type cmd_type)
194 {
195 	struct wlan_serialization_queued_cmd_info cmd = {0};
196 
197 	mlme_debug("Remove the cmd type:%d", cmd_type);
198 
199 	cmd.vdev = vdev;
200 	cmd.cmd_id = cmd_id;
201 	cmd.cmd_type = cmd_type;
202 	cmd.requestor = WLAN_UMAC_COMP_MLME;
203 	cmd.req_type = WLAN_SER_CANCEL_NON_SCAN_CMD;
204 	cmd.queue_type = WLAN_SERIALIZATION_ACTIVE_QUEUE;
205 
206 	/* Inform serialization for command completion */
207 	wlan_serialization_remove_cmd(&cmd);
208 }
209 
210 void
211 wlan_vdev_mlme_ser_cancel_request(struct wlan_objmgr_vdev *vdev,
212 				  enum wlan_serialization_cmd_type cmd_type,
213 				  enum wlan_serialization_cancel_type req_type)
214 {
215 	struct wlan_serialization_queued_cmd_info cmd = {0};
216 
217 	cmd.vdev = vdev;
218 	cmd.cmd_type = cmd_type;
219 	cmd.req_type = req_type;
220 	cmd.requestor = WLAN_UMAC_COMP_MLME;
221 	cmd.queue_type = WLAN_SERIALIZATION_PENDING_QUEUE;
222 
223 	wlan_serialization_cancel_request(&cmd);
224 }
225 
226 void
227 mlme_ser_inc_act_cmd_timeout(struct wlan_serialization_command *cmd)
228 {
229 	mlme_debug("Increase timeout of cmd type:%d", cmd->cmd_type);
230 	wlan_serialization_update_timer(cmd);
231 }
232