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