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