1 /*
2  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /**
19  * DOC: Implements MLME component object creation/initialization/destroy
20  */
21 
22 #include <wlan_objmgr_cmn.h>
23 #include <wlan_objmgr_global_obj.h>
24 #include <wlan_objmgr_vdev_obj.h>
25 #include <wlan_mlme_dbg.h>
26 #include <include/wlan_mlme_cmn.h>
27 #include <include/wlan_vdev_mlme.h>
28 #include <include/wlan_pdev_mlme.h>
29 #include <vdev_mgr/core/src/vdev_mlme_sm.h>
30 #include <wlan_pdev_mlme_api.h>
31 #include <wlan_vdev_mlme_api.h>
32 #include <wlan_serialization_api.h>
33 #include <wlan_utility.h>
34 #include <cdp_txrx_cmn.h>
35 #include <wlan_lmac_if_def.h>
36 #include <target_if_vdev_mgr_tx_ops.h>
37 #include "connection_mgr/core/src/wlan_cm_main.h"
38 #include <wlan_mlo_mgr_public_api.h>
39 
mlme_vdev_obj_create_handler(struct wlan_objmgr_vdev * vdev,void * arg)40 static QDF_STATUS mlme_vdev_obj_create_handler(struct wlan_objmgr_vdev *vdev,
41 					       void *arg)
42 {
43 	struct vdev_mlme_obj *vdev_mlme;
44 	struct wlan_objmgr_pdev *pdev;
45 	struct wlan_objmgr_psoc *psoc;
46 	struct pdev_mlme_obj *pdev_mlme;
47 	struct wlan_lmac_if_mlme_tx_ops *txops;
48 	QDF_STATUS status;
49 
50 	if (!vdev) {
51 		mlme_err(" VDEV is NULL");
52 		return QDF_STATUS_E_FAILURE;
53 	}
54 
55 	pdev = wlan_vdev_get_pdev(vdev);
56 	if (!pdev) {
57 		mlme_err(" PDEV is NULL");
58 		return QDF_STATUS_E_FAILURE;
59 	}
60 
61 	/**
62 	 * 1st check whether for this vdev any vdev commands are pending for
63 	 * response.
64 	 */
65 	psoc = wlan_pdev_get_psoc(pdev);
66 	if (!psoc) {
67 		mlme_err("PSOC is NULL");
68 		return QDF_STATUS_E_FAILURE;
69 	}
70 
71 	txops = wlan_mlme_get_lmac_tx_ops(psoc);
72 	if (!txops || !txops->psoc_vdev_rsp_timer_inuse) {
73 		mlme_err("Failed to get mlme txrx_ops PSOC_%d",
74 			 wlan_psoc_get_id(psoc));
75 		return QDF_STATUS_E_FAILURE;
76 	}
77 
78 	status = txops->psoc_vdev_rsp_timer_inuse(psoc, wlan_vdev_get_id(vdev));
79 	if (QDF_IS_STATUS_ERROR(status)) {
80 		if (status == QDF_STATUS_E_ALREADY) {
81 			mlme_err("Go through, since timer initializes later.");
82 		} else {
83 			mlme_err("The vdev response is pending for VDEV_%d status:%d",
84 				 wlan_vdev_get_id(vdev), status);
85 			return QDF_STATUS_E_FAILURE;
86 		}
87 	}
88 
89 	pdev_mlme = wlan_pdev_mlme_get_cmpt_obj(pdev);
90 	if (!pdev_mlme) {
91 		mlme_err("PDEV MLME is NULL");
92 		return QDF_STATUS_E_FAILURE;
93 	}
94 
95 	vdev_mlme = qdf_mem_malloc(sizeof(*vdev_mlme));
96 	if (!vdev_mlme)
97 		return QDF_STATUS_E_NOMEM;
98 	wlan_minidump_log(vdev_mlme, sizeof(*vdev_mlme), psoc,
99 			  WLAN_MD_OBJMGR_VDEV_MLME, "vdev_mlme");
100 
101 	vdev_mlme->vdev = vdev;
102 
103 	if (pdev_mlme->mlme_register_ops(vdev_mlme) != QDF_STATUS_SUCCESS) {
104 		mlme_err("Callbacks registration is failed");
105 		goto init_failed;
106 	}
107 
108 	if (mlme_vdev_sm_create(vdev_mlme) != QDF_STATUS_SUCCESS) {
109 		mlme_err("SME creation failed");
110 		goto init_failed;
111 	}
112 
113 	if (QDF_IS_STATUS_ERROR(wlan_cm_init(vdev_mlme))) {
114 		mlme_err("CM SM create failed");
115 		goto cm_sm_create_failed;
116 	}
117 
118 	if (mlme_vdev_ops_ext_hdl_create(vdev_mlme) !=
119 						QDF_STATUS_SUCCESS) {
120 		mlme_err("Legacy vdev object creation failed");
121 		goto ext_hdl_create_failed;
122 	}
123 
124 	qdf_timer_init(NULL, &vdev_mlme->ml_reconfig_timer,
125 		       mlme_vdev_reconfig_timer_cb, (void *)(vdev_mlme),
126 		       QDF_TIMER_TYPE_WAKE_APPS);
127 
128 	wlan_objmgr_vdev_component_obj_attach((struct wlan_objmgr_vdev *)vdev,
129 					      WLAN_UMAC_COMP_MLME,
130 					      (void *)vdev_mlme,
131 					      QDF_STATUS_SUCCESS);
132 
133 	if (mlme_vdev_ops_ext_hdl_post_create(vdev_mlme) !=
134 						QDF_STATUS_SUCCESS) {
135 		mlme_err("Legacy vdev object post creation failed");
136 		goto ext_hdl_post_create_failed;
137 	}
138 
139 	qdf_mem_set(vdev_mlme->mgmt.rate_info.ratemask_params,
140 		    WLAN_VDEV_RATEMASK_TYPE_MAX *
141 		    sizeof(struct vdev_ratemask_params), 0xFF);
142 
143 	return QDF_STATUS_SUCCESS;
144 
145 ext_hdl_post_create_failed:
146 	qdf_timer_free(&vdev_mlme->ml_reconfig_timer);
147 	mlme_vdev_ops_ext_hdl_destroy(vdev_mlme);
148 	wlan_objmgr_vdev_component_obj_detach(vdev, WLAN_UMAC_COMP_MLME,
149 					      vdev_mlme);
150 ext_hdl_create_failed:
151 	wlan_cm_deinit(vdev_mlme);
152 cm_sm_create_failed:
153 	mlme_vdev_sm_destroy(vdev_mlme);
154 init_failed:
155 	wlan_minidump_remove(vdev_mlme, sizeof(*vdev_mlme), psoc,
156 			     WLAN_MD_OBJMGR_VDEV_MLME, "vdev_mlme");
157 
158 	qdf_mem_free(vdev_mlme);
159 	return QDF_STATUS_E_FAILURE;
160 }
161 
mlme_vdev_obj_destroy_handler(struct wlan_objmgr_vdev * vdev,void * arg)162 static QDF_STATUS mlme_vdev_obj_destroy_handler(struct wlan_objmgr_vdev *vdev,
163 						void *arg)
164 {
165 	struct vdev_mlme_obj *vdev_mlme;
166 
167 	if (!vdev) {
168 		mlme_err(" VDEV is NULL");
169 		return QDF_STATUS_E_FAILURE;
170 	}
171 
172 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
173 	if (!vdev_mlme) {
174 		mlme_info(" VDEV MLME component object is NULL");
175 		return QDF_STATUS_SUCCESS;
176 	}
177 
178 	qdf_timer_free(&vdev_mlme->ml_reconfig_timer);
179 	wlan_cm_deinit(vdev_mlme);
180 	mlme_vdev_sm_destroy(vdev_mlme);
181 	mlme_vdev_ops_ext_hdl_destroy(vdev_mlme);
182 	wlan_objmgr_vdev_component_obj_detach(vdev, WLAN_UMAC_COMP_MLME,
183 					      vdev_mlme);
184 
185 	wlan_minidump_remove(vdev_mlme, sizeof(*vdev_mlme),
186 			     wlan_vdev_get_psoc(vdev),
187 			     WLAN_MD_OBJMGR_VDEV_MLME, "vdev_mlme");
188 
189 	qdf_mem_free(vdev_mlme);
190 
191 	return QDF_STATUS_SUCCESS;
192 }
193 
mlme_scan_serialization_comp_info_cb(struct wlan_objmgr_vdev * vdev,union wlan_serialization_rules_info * comp_info,struct wlan_serialization_command * cmd)194 static void mlme_scan_serialization_comp_info_cb(
195 		struct wlan_objmgr_vdev *vdev,
196 		union wlan_serialization_rules_info *comp_info,
197 		struct wlan_serialization_command *cmd)
198 {
199 	struct wlan_objmgr_pdev *pdev;
200 	struct scan_start_request *scan_start_req = cmd->umac_cmd;
201 	QDF_STATUS status;
202 
203 	if (!comp_info || !vdev) {
204 		mlme_err("comp_info or vdev is NULL");
205 		return;
206 	}
207 
208 	pdev = wlan_vdev_get_pdev(vdev);
209 	if (!pdev) {
210 		mlme_err("pdev is NULL");
211 		return;
212 	}
213 
214 	if (!scan_start_req) {
215 		mlme_err("scan start request is null");
216 		return;
217 	}
218 
219 	comp_info->scan_info.is_scan_for_connect = false;
220 
221 	if (cmd->cmd_type == WLAN_SER_CMD_SCAN &&
222 	    scan_start_req->scan_req.scan_type == SCAN_TYPE_SCAN_FOR_CONNECT) {
223 		comp_info->scan_info.is_scan_for_connect = true;
224 	}
225 
226 	comp_info->scan_info.is_mlme_op_in_progress = false;
227 
228 	status = wlan_util_is_pdev_scan_allowed(pdev, WLAN_MLME_SER_IF_ID);
229 	if (status != QDF_STATUS_SUCCESS)
230 		comp_info->scan_info.is_mlme_op_in_progress = true;
231 }
232 
wlan_mlme_psoc_enable(struct wlan_objmgr_psoc * psoc)233 QDF_STATUS wlan_mlme_psoc_enable(struct wlan_objmgr_psoc *psoc)
234 {
235 	QDF_STATUS status;
236 	struct wlan_lmac_if_mlme_tx_ops *tx_ops;
237 
238 	status = mlme_psoc_ext_enable_cb(psoc);
239 	if (QDF_IS_STATUS_ERROR(status)) {
240 		mlme_err("Failed to register enable mlme ext param handler cb");
241 		return status;
242 	}
243 
244 	status = wlan_serialization_register_comp_info_cb
245 			(psoc,
246 			 WLAN_UMAC_COMP_MLME,
247 			 WLAN_SER_CMD_SCAN,
248 			 mlme_scan_serialization_comp_info_cb);
249 	if (QDF_IS_STATUS_ERROR(status)) {
250 		mlme_err("Serialize scan cmd register failed");
251 		mlme_psoc_ext_disable_cb(psoc);
252 		return status;
253 	}
254 
255 	/* Register for WMI events into target_if rx  */
256 	tx_ops = wlan_mlme_get_lmac_tx_ops(psoc);
257 	if (tx_ops && tx_ops->vdev_mlme_attach)
258 		tx_ops->vdev_mlme_attach(psoc);
259 
260 	return status;
261 }
262 
wlan_mlme_psoc_disable(struct wlan_objmgr_psoc * psoc)263 QDF_STATUS wlan_mlme_psoc_disable(struct wlan_objmgr_psoc *psoc)
264 {
265 	QDF_STATUS status;
266 	struct wlan_lmac_if_mlme_tx_ops *tx_ops;
267 
268 	/* Unregister WMI events  */
269 	tx_ops = wlan_mlme_get_lmac_tx_ops(psoc);
270 	if (tx_ops && tx_ops->vdev_mlme_detach)
271 		tx_ops->vdev_mlme_detach(psoc);
272 
273 	status = wlan_serialization_deregister_comp_info_cb
274 						(psoc,
275 						 WLAN_UMAC_COMP_MLME,
276 						 WLAN_SER_CMD_SCAN);
277 	if (QDF_IS_STATUS_ERROR(status))
278 		mlme_err("Serialize scan cmd deregister failed");
279 
280 	status = mlme_psoc_ext_disable_cb(psoc);
281 	if (QDF_IS_STATUS_ERROR(status))
282 		mlme_err("Failed to unregister enable mlme ext param hdl cb");
283 
284 	return status;
285 }
286 
wlan_vdev_mlme_init(void)287 QDF_STATUS wlan_vdev_mlme_init(void)
288 {
289 	if (wlan_objmgr_register_vdev_create_handler
290 				(WLAN_UMAC_COMP_MLME,
291 				 mlme_vdev_obj_create_handler, NULL)
292 						!= QDF_STATUS_SUCCESS)
293 		return QDF_STATUS_E_FAILURE;
294 
295 	if (wlan_objmgr_register_vdev_destroy_handler
296 				(WLAN_UMAC_COMP_MLME,
297 				 mlme_vdev_obj_destroy_handler, NULL)
298 						!= QDF_STATUS_SUCCESS) {
299 		if (wlan_objmgr_unregister_vdev_create_handler
300 					(WLAN_UMAC_COMP_MLME,
301 					 mlme_vdev_obj_create_handler, NULL)
302 						!= QDF_STATUS_SUCCESS)
303 			return QDF_STATUS_E_FAILURE;
304 
305 		return QDF_STATUS_E_FAILURE;
306 	}
307 
308 	return QDF_STATUS_SUCCESS;
309 }
310 
wlan_vdev_mlme_deinit(void)311 QDF_STATUS wlan_vdev_mlme_deinit(void)
312 {
313 	if (wlan_objmgr_unregister_vdev_create_handler
314 				(WLAN_UMAC_COMP_MLME,
315 				 mlme_vdev_obj_create_handler, NULL)
316 					!= QDF_STATUS_SUCCESS)
317 		return QDF_STATUS_E_FAILURE;
318 
319 	if (wlan_objmgr_unregister_vdev_destroy_handler
320 				(WLAN_UMAC_COMP_MLME,
321 				 mlme_vdev_obj_destroy_handler, NULL)
322 						!= QDF_STATUS_SUCCESS)
323 		return QDF_STATUS_E_FAILURE;
324 
325 	return QDF_STATUS_SUCCESS;
326 }
327 
328 #ifdef WLAN_FEATURE_DYNAMIC_MAC_ADDR_UPDATE
wlan_vdev_mlme_send_set_mac_addr(struct qdf_mac_addr mac_addr,struct qdf_mac_addr mld_addr,struct wlan_objmgr_vdev * vdev)329 QDF_STATUS wlan_vdev_mlme_send_set_mac_addr(struct qdf_mac_addr mac_addr,
330 					    struct qdf_mac_addr mld_addr,
331 					    struct wlan_objmgr_vdev *vdev)
332 {
333 	return mlme_vdev_ops_send_set_mac_address(mac_addr, mld_addr, vdev);
334 }
335 
wlan_vdev_mlme_notify_set_mac_addr_response(struct wlan_objmgr_vdev * vdev,uint8_t resp_status)336 void wlan_vdev_mlme_notify_set_mac_addr_response(struct wlan_objmgr_vdev *vdev,
337 						 uint8_t resp_status)
338 {
339 	if (wlan_vdev_mlme_is_mlo_link_switch_in_progress(vdev)) {
340 		wlan_mlo_mgr_link_switch_set_mac_addr_resp(vdev, resp_status);
341 		return;
342 	}
343 
344 	mlme_vdev_mgr_notify_set_mac_addr_response(wlan_vdev_get_id(vdev),
345 						   resp_status);
346 }
347 #endif
348