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