1 /*
2  * Copyright (c) 2020-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: contains interface manager public api
20  */
21 #include "wlan_objmgr_psoc_obj.h"
22 #include "wlan_objmgr_vdev_obj.h"
23 #include "wlan_if_mgr_public_struct.h"
24 #include "wlan_if_mgr_sta.h"
25 #include "wlan_if_mgr_roam.h"
26 #include "wlan_if_mgr_main.h"
27 #include "nan_ucfg_api.h"
28 #include "wlan_policy_mgr_api.h"
29 #include "wlan_p2p_ucfg_api.h"
30 #include "wlan_tdls_ucfg_api.h"
31 #include "wlan_tdls_api.h"
32 #include <wlan_cm_api.h>
33 #include <wlan_mlo_mgr_public_structs.h>
34 #include <wlan_mlo_mgr_cmn.h>
35 #include <wlan_cm_roam_api.h>
36 #include "wlan_nan_api.h"
37 #include "wlan_mlme_vdev_mgr_interface.h"
38 #include <wlan_mlo_mgr_sta.h>
39 #include "wlan_vdev_mgr_utils_api.h"
40 #include "wlan_tdls_api.h"
41 #include "wlan_mlo_mgr_link_switch.h"
42 #include "wlan_ll_sap_api.h"
43 
if_mgr_connect_start(struct wlan_objmgr_vdev * vdev,struct if_mgr_event_data * event_data)44 QDF_STATUS if_mgr_connect_start(struct wlan_objmgr_vdev *vdev,
45 				struct if_mgr_event_data *event_data)
46 {
47 	uint8_t sta_cnt, sap_cnt;
48 	struct wlan_objmgr_pdev *pdev;
49 	struct wlan_objmgr_psoc *psoc;
50 	enum QDF_OPMODE op_mode;
51 	uint8_t vdev_id_list[MAX_NUMBER_OF_CONC_CONNECTIONS], i;
52 	bool disable_nan = true;
53 
54 	pdev = wlan_vdev_get_pdev(vdev);
55 	if (!pdev)
56 		return QDF_STATUS_E_FAILURE;
57 
58 	psoc = wlan_pdev_get_psoc(pdev);
59 	if (!psoc)
60 		return QDF_STATUS_E_FAILURE;
61 
62 	/*
63 	 * Disable NAN Discovery if incoming connection is P2P or if a STA
64 	 * connection already exists and if this is a case of STA+STA
65 	 * or SAP+STA concurrency
66 	 */
67 	sta_cnt = policy_mgr_get_mode_specific_conn_info(psoc, NULL,
68 							 vdev_id_list,
69 							 PM_STA_MODE);
70 	sap_cnt = policy_mgr_get_sap_mode_info(psoc, NULL,
71 					       &vdev_id_list[sta_cnt]);
72 
73 	op_mode = wlan_vdev_mlme_get_opmode(vdev);
74 
75 	if (op_mode == QDF_STA_MODE || op_mode == QDF_P2P_CLIENT_MODE)
76 		wlan_handle_emlsr_sta_concurrency(psoc, true, false);
77 
78 	if (op_mode == QDF_P2P_CLIENT_MODE || sap_cnt || sta_cnt) {
79 		for (i = 0; i < sta_cnt + sap_cnt; i++) {
80 			if (vdev_id_list[i] == wlan_vdev_get_id(vdev))
81 				disable_nan = false;
82 			/* 1. Don't disable nan if firmware supports
83 			 *    ML STA + NAN + NDP.
84 			 * 2. Disable nan if legacy sta + nan +
85 			 *    ML STA(primary link) comes up.
86 			 */
87 			if (wlan_vdev_mlme_is_mlo_link_vdev(vdev) &&
88 			    wlan_is_mlo_sta_nan_ndi_allowed(psoc))
89 				disable_nan = false;
90 		}
91 		if (disable_nan)
92 			ucfg_nan_disable_concurrency(psoc);
93 	}
94 
95 	if (op_mode == QDF_P2P_CLIENT_MODE)
96 		wlan_tdls_handle_p2p_client_connect(psoc, vdev);
97 
98 	/*
99 	 * STA+NDI concurrency gets preference over NDI+NDI. Disable
100 	 * first NDI in case an NDI+NDI concurrency exists if FW does
101 	 * not support 4 port concurrency of two NDI + NAN with STA.
102 	 */
103 	if (!ucfg_nan_is_sta_nan_ndi_4_port_allowed(psoc))
104 		ucfg_nan_check_and_disable_unsupported_ndi(psoc,
105 							   false);
106 
107 	return QDF_STATUS_SUCCESS;
108 }
109 
if_mgr_connect_active(struct wlan_objmgr_vdev * vdev,struct if_mgr_event_data * event_data)110 QDF_STATUS if_mgr_connect_active(struct wlan_objmgr_vdev *vdev,
111 				 struct if_mgr_event_data *event_data)
112 {
113 	struct wlan_objmgr_pdev *pdev;
114 
115 	pdev = wlan_vdev_get_pdev(vdev);
116 	if (!pdev)
117 		return QDF_STATUS_E_FAILURE;
118 
119 	if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev)) {
120 		/*
121 		 * In case of STA+STA concurrency, firmware might try to roam
122 		 * to same AP where host is trying to do association on the other
123 		 * STA iface. Roaming is disabled on all the ifaces to avoid
124 		 * this scenario.
125 		 */
126 		if_mgr_disable_roaming(pdev, vdev, RSO_CONNECT_START);
127 	}
128 
129 	return QDF_STATUS_SUCCESS;
130 }
131 
if_mgr_connect_complete(struct wlan_objmgr_vdev * vdev,struct if_mgr_event_data * event_data)132 QDF_STATUS if_mgr_connect_complete(struct wlan_objmgr_vdev *vdev,
133 				   struct if_mgr_event_data *event_data)
134 {
135 	struct wlan_objmgr_psoc *psoc;
136 	struct wlan_objmgr_pdev *pdev;
137 	QDF_STATUS status = event_data->status;
138 	uint8_t vdev_id;
139 
140 	pdev = wlan_vdev_get_pdev(vdev);
141 	if (!pdev)
142 		return QDF_STATUS_E_FAILURE;
143 
144 	psoc = wlan_pdev_get_psoc(pdev);
145 	if (!psoc)
146 		return QDF_STATUS_E_FAILURE;
147 
148 	vdev_id = wlan_vdev_get_id(vdev);
149 	if (QDF_IS_STATUS_SUCCESS(status)) {
150 		/*
151 		 * Due to audio share glitch with P2P clients caused by roam
152 		 * scan on concurrent interface, disable roaming if
153 		 * "p2p_disable_roam" ini is enabled. Donot re-enable roaming
154 		 * again on other STA interface if p2p client connection is
155 		 * active on any vdev.
156 		 */
157 		if (ucfg_p2p_is_roam_config_disabled(psoc) &&
158 		    wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_CLIENT_MODE) {
159 			ifmgr_debug("p2p client active, keep roam disabled");
160 		} else {
161 			ifmgr_debug("set pcl when connection on vdev id:%d",
162 				     vdev_id);
163 			policy_mgr_set_pcl_for_connected_vdev(psoc, vdev_id,
164 							      false);
165 			/*
166 			 * Enable roaming on other STA iface except this one.
167 			 * Firmware doesn't support connection on one STA iface
168 			 * while roaming on other STA iface.
169 			 */
170 			if_mgr_enable_roaming(pdev, vdev, RSO_CONNECT_START);
171 		}
172 	} else {
173 		/* notify connect failure on final failure */
174 		ucfg_tdls_notify_connect_failure(psoc);
175 
176 		/*
177 		 * Enable roaming on other STA iface except this one.
178 		 * Firmware doesn't support connection on one STA iface
179 		 * while roaming on other STA iface.
180 		 */
181 		if_mgr_enable_roaming(pdev, vdev, RSO_CONNECT_START);
182 	}
183 
184 	policy_mgr_check_n_start_opportunistic_timer(psoc);
185 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE &&
186 	    wlan_vdev_mlme_is_mlo_vdev(vdev))
187 		wlan_handle_emlsr_sta_concurrency(psoc, false, true);
188 
189 	if (!wlan_cm_is_vdev_roaming(vdev))
190 		policy_mgr_check_concurrent_intf_and_restart_sap(psoc,
191 				wlan_util_vdev_mgr_get_acs_mode_for_vdev(vdev));
192 
193 	wlan_ll_sap_switch_bearer_on_sta_connect_complete(psoc, vdev_id);
194 
195 	return QDF_STATUS_SUCCESS;
196 }
197 
if_mgr_disconnect_start(struct wlan_objmgr_vdev * vdev,struct if_mgr_event_data * event_data)198 QDF_STATUS if_mgr_disconnect_start(struct wlan_objmgr_vdev *vdev,
199 				   struct if_mgr_event_data *event_data)
200 {
201 	struct wlan_objmgr_psoc *psoc;
202 	struct wlan_objmgr_pdev *pdev;
203 	struct mlme_legacy_priv *mlme_priv;
204 
205 	pdev = wlan_vdev_get_pdev(vdev);
206 	if (!pdev)
207 		return QDF_STATUS_E_FAILURE;
208 
209 	psoc = wlan_pdev_get_psoc(pdev);
210 	if (!psoc)
211 		return QDF_STATUS_E_FAILURE;
212 
213 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
214 	if (!mlme_priv)
215 		return QDF_STATUS_E_FAILURE;
216 
217 	qdf_runtime_pm_prevent_suspend(&mlme_priv->disconnect_runtime_lock);
218 
219 	return QDF_STATUS_SUCCESS;
220 }
221 
if_mgr_disconnect_complete(struct wlan_objmgr_vdev * vdev,struct if_mgr_event_data * event_data)222 QDF_STATUS if_mgr_disconnect_complete(struct wlan_objmgr_vdev *vdev,
223 				      struct if_mgr_event_data *event_data)
224 {
225 	struct wlan_objmgr_psoc *psoc;
226 	struct wlan_objmgr_pdev *pdev;
227 	struct mlme_legacy_priv *mlme_priv;
228 	QDF_STATUS status;
229 
230 	pdev = wlan_vdev_get_pdev(vdev);
231 	if (!pdev)
232 		return QDF_STATUS_E_FAILURE;
233 
234 	psoc = wlan_pdev_get_psoc(pdev);
235 	if (!psoc)
236 		return QDF_STATUS_E_FAILURE;
237 
238 	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
239 	if (!mlme_priv)
240 		return QDF_STATUS_E_FAILURE;
241 
242 	qdf_runtime_pm_allow_suspend(&mlme_priv->disconnect_runtime_lock);
243 
244 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE ||
245 	    wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_CLIENT_MODE)
246 		wlan_handle_emlsr_sta_concurrency(psoc, false, true);
247 
248 	status = if_mgr_enable_roaming_after_p2p_disconnect(pdev, vdev,
249 							    RSO_CONNECT_START);
250 	if (status) {
251 		ifmgr_err("Failed to enable roaming after p2p disconnect");
252 		return status;
253 	}
254 	if (!mlo_is_mld_sta(vdev) || !mlo_mgr_is_link_switch_in_progress(vdev))
255 		policy_mgr_check_concurrent_intf_and_restart_sap(
256 			psoc, wlan_util_vdev_mgr_get_acs_mode_for_vdev(vdev));
257 
258 	status = if_mgr_enable_roaming_on_connected_sta(pdev, vdev);
259 	if (status) {
260 		ifmgr_err("Failed to enable roaming on connected sta");
261 		return status;
262 	}
263 
264 	return QDF_STATUS_SUCCESS;
265 }
266 
267 QDF_STATUS
if_mgr_sta_csa_complete(struct wlan_objmgr_vdev * vdev,struct if_mgr_event_data * event_data)268 if_mgr_sta_csa_complete(struct wlan_objmgr_vdev *vdev,
269 			struct if_mgr_event_data *event_data)
270 {
271 	struct wlan_objmgr_psoc *psoc;
272 	struct wlan_objmgr_pdev *pdev;
273 
274 	pdev = wlan_vdev_get_pdev(vdev);
275 	if (!pdev)
276 		return QDF_STATUS_E_FAILURE;
277 
278 	psoc = wlan_pdev_get_psoc(pdev);
279 	if (!psoc)
280 		return QDF_STATUS_E_FAILURE;
281 
282 	wlan_tdls_notify_channel_switch_complete(psoc, wlan_vdev_get_id(vdev));
283 
284 	return QDF_STATUS_SUCCESS;
285 }
286