1 /*
2  * Copyright (c) 2020, 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_ap.h"
25 #include "wlan_if_mgr_roam.h"
26 #include "wlan_policy_mgr_api.h"
27 #include "wlan_if_mgr_main.h"
28 #include "wlan_p2p_cfg_api.h"
29 #include "wlan_tdls_api.h"
30 #include "wlan_p2p_api.h"
31 #include "wlan_mlme_vdev_mgr_interface.h"
32 #include "wlan_p2p_ucfg_api.h"
33 #include "wlan_vdev_mgr_utils_api.h"
34 #include "wlan_tdls_tgt_api.h"
35 #include "wlan_policy_mgr_ll_sap.h"
36 
if_mgr_ap_start_bss(struct wlan_objmgr_vdev * vdev,struct if_mgr_event_data * event_data)37 QDF_STATUS if_mgr_ap_start_bss(struct wlan_objmgr_vdev *vdev,
38 			       struct if_mgr_event_data *event_data)
39 {
40 	struct wlan_objmgr_psoc *psoc;
41 	struct wlan_objmgr_pdev *pdev;
42 	QDF_STATUS status;
43 
44 	pdev = wlan_vdev_get_pdev(vdev);
45 	if (!pdev)
46 		return QDF_STATUS_E_FAILURE;
47 
48 	psoc = wlan_pdev_get_psoc(pdev);
49 	if (!psoc)
50 		return QDF_STATUS_E_FAILURE;
51 
52 	wlan_tdls_notify_start_bss(psoc, vdev);
53 
54 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE ||
55 	    wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_GO_MODE)
56 		wlan_handle_emlsr_sta_concurrency(psoc, true, false);
57 
58 	if (policy_mgr_is_hw_mode_change_in_progress(psoc)) {
59 		if (!QDF_IS_STATUS_SUCCESS(
60 		    policy_mgr_wait_for_connection_update(psoc))) {
61 			ifmgr_err("qdf wait for event failed!!");
62 			return QDF_STATUS_E_FAILURE;
63 		}
64 	}
65 	if (policy_mgr_is_chan_switch_in_progress(psoc)) {
66 		status = policy_mgr_wait_chan_switch_complete_evt(psoc);
67 		if (!QDF_IS_STATUS_SUCCESS(status)) {
68 			ifmgr_err("qdf wait for csa event failed!!");
69 			return QDF_STATUS_E_FAILURE;
70 		}
71 	}
72 
73 	if (policy_mgr_is_sta_active_connection_exists(psoc))
74 		/* Disable Roaming on all vdev's before starting bss */
75 		if_mgr_disable_roaming(pdev, vdev, RSO_START_BSS);
76 
77 	/* abort p2p roc before starting the BSS for sync event */
78 	ucfg_p2p_cleanup_roc_by_psoc(psoc);
79 
80 	return QDF_STATUS_SUCCESS;
81 }
82 
83 QDF_STATUS
if_mgr_ap_start_bss_complete(struct wlan_objmgr_vdev * vdev,struct if_mgr_event_data * event_data)84 if_mgr_ap_start_bss_complete(struct wlan_objmgr_vdev *vdev,
85 			     struct if_mgr_event_data *event_data)
86 {
87 	struct wlan_objmgr_psoc *psoc;
88 	struct wlan_objmgr_pdev *pdev;
89 
90 	pdev = wlan_vdev_get_pdev(vdev);
91 	if (!pdev)
92 		return QDF_STATUS_E_FAILURE;
93 
94 	psoc = wlan_pdev_get_psoc(pdev);
95 	if (!psoc)
96 		return QDF_STATUS_E_FAILURE;
97 
98 	/*
99 	 * Due to audio share glitch with P2P GO caused by
100 	 * roam scan on concurrent interface, disable
101 	 * roaming if "p2p_disable_roam" ini is enabled.
102 	 * Donot re-enable roaming again on other STA interface
103 	 * if p2p GO is active on any vdev.
104 	 */
105 	if (cfg_p2p_is_roam_config_disabled(psoc) &&
106 	    wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_GO_MODE) {
107 		ifmgr_debug("p2p go mode, keep roam disabled");
108 	} else {
109 		/* Enable Roaming after start bss in case of failure/success */
110 		if_mgr_enable_roaming(pdev, vdev, RSO_START_BSS);
111 	}
112 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_GO_MODE)
113 		policy_mgr_check_sap_go_force_scc(psoc, vdev,
114 						  CSA_REASON_GO_BSS_STARTED);
115 	ifmgr_debug("check for SAP restart");
116 
117 	if (policy_mgr_is_vdev_ll_lt_sap(psoc, wlan_vdev_get_id(vdev)))
118 		policy_mgr_ll_lt_sap_restart_concurrent_sap(psoc, true);
119 	else
120 		policy_mgr_check_concurrent_intf_and_restart_sap(
121 				psoc,
122 				wlan_util_vdev_mgr_get_acs_mode_for_vdev(vdev));
123 	/*
124 	 * Enable TDLS again on concurrent STA
125 	 */
126 	if (event_data && QDF_IS_STATUS_ERROR(event_data->status))
127 		wlan_tdls_notify_start_bss_failure(psoc);
128 
129 	return QDF_STATUS_SUCCESS;
130 }
131 
if_mgr_ap_stop_bss(struct wlan_objmgr_vdev * vdev,struct if_mgr_event_data * event_data)132 QDF_STATUS if_mgr_ap_stop_bss(struct wlan_objmgr_vdev *vdev,
133 			      struct if_mgr_event_data *event_data)
134 {
135 	return QDF_STATUS_SUCCESS;
136 }
137 
138 QDF_STATUS
if_mgr_ap_stop_bss_complete(struct wlan_objmgr_vdev * vdev,struct if_mgr_event_data * event_data)139 if_mgr_ap_stop_bss_complete(struct wlan_objmgr_vdev *vdev,
140 			    struct if_mgr_event_data *event_data)
141 {
142 	struct wlan_objmgr_psoc *psoc;
143 	struct wlan_objmgr_pdev *pdev;
144 	uint8_t mcc_scc_switch;
145 
146 	pdev = wlan_vdev_get_pdev(vdev);
147 	if (!pdev)
148 		return QDF_STATUS_E_FAILURE;
149 
150 	psoc = wlan_pdev_get_psoc(pdev);
151 	if (!psoc)
152 		return QDF_STATUS_E_FAILURE;
153 
154 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE ||
155 	    wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_GO_MODE)
156 		wlan_handle_emlsr_sta_concurrency(psoc, false, true);
157 	/*
158 	 * Due to audio share glitch with P2P GO caused by
159 	 * roam scan on concurrent interface, disable
160 	 * roaming if "p2p_disable_roam" ini is enabled.
161 	 * Re-enable roaming on other STA interface if p2p GO
162 	 * is active on any vdev.
163 	 */
164 	if (cfg_p2p_is_roam_config_disabled(psoc) &&
165 	    wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_GO_MODE) {
166 		ifmgr_debug("p2p go disconnected enable roam");
167 		if_mgr_enable_roaming(pdev, vdev, RSO_START_BSS);
168 	}
169 
170 	ifmgr_debug("SAP/P2P-GO is stopped, re-enable roaming if it's stopped due to SAP/P2P-GO CSA");
171 	if_mgr_enable_roaming(pdev, vdev, RSO_SAP_CHANNEL_CHANGE);
172 
173 	policy_mgr_get_mcc_scc_switch(psoc, &mcc_scc_switch);
174 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_GO_MODE &&
175 	    mcc_scc_switch == QDF_MCC_TO_SCC_SWITCH_WITH_FAVORITE_CHANNEL)
176 		policy_mgr_check_concurrent_intf_and_restart_sap(psoc, false);
177 
178 	if (policy_mgr_is_vdev_ll_lt_sap(psoc, wlan_vdev_get_id(vdev)))
179 		policy_mgr_ll_lt_sap_restart_concurrent_sap(psoc, false);
180 
181 	return QDF_STATUS_SUCCESS;
182 }
183 
184 QDF_STATUS
if_mgr_ap_csa_complete(struct wlan_objmgr_vdev * vdev,struct if_mgr_event_data * event_data)185 if_mgr_ap_csa_complete(struct wlan_objmgr_vdev *vdev,
186 		       struct if_mgr_event_data *event_data)
187 {
188 	struct wlan_objmgr_psoc *psoc;
189 	struct wlan_objmgr_pdev *pdev;
190 	QDF_STATUS status = QDF_STATUS_SUCCESS;
191 
192 	pdev = wlan_vdev_get_pdev(vdev);
193 	if (!pdev)
194 		return QDF_STATUS_E_FAILURE;
195 
196 	psoc = wlan_pdev_get_psoc(pdev);
197 	if (!psoc)
198 		return QDF_STATUS_E_FAILURE;
199 
200 	status = wlan_p2p_check_and_force_scc_go_plus_go(psoc, vdev);
201 	if (QDF_IS_STATUS_ERROR(status))
202 		ifmgr_err("force scc failure with status: %d", status);
203 
204 	wlan_tdls_notify_channel_switch_complete(psoc, wlan_vdev_get_id(vdev));
205 
206 	return status;
207 }
208 
209 QDF_STATUS
if_mgr_ap_csa_start(struct wlan_objmgr_vdev * vdev,struct if_mgr_event_data * event_data)210 if_mgr_ap_csa_start(struct wlan_objmgr_vdev *vdev,
211 		    struct if_mgr_event_data *event_data)
212 {
213 	struct wlan_objmgr_psoc *psoc;
214 	struct wlan_objmgr_pdev *pdev;
215 	enum QDF_OPMODE op_mode;
216 
217 	op_mode = wlan_vdev_mlme_get_opmode(vdev);
218 	if (op_mode != QDF_SAP_MODE && op_mode != QDF_P2P_GO_MODE)
219 		return QDF_STATUS_SUCCESS;
220 
221 	pdev = wlan_vdev_get_pdev(vdev);
222 	if (!pdev)
223 		return QDF_STATUS_E_FAILURE;
224 
225 	psoc = wlan_pdev_get_psoc(pdev);
226 	if (!psoc)
227 		return QDF_STATUS_E_FAILURE;
228 
229 	/*
230 	 * Disable TDLS off-channel before VDEV restart
231 	 */
232 	wlan_tdls_notify_channel_switch_start(psoc, vdev);
233 
234 	return QDF_STATUS_SUCCESS;
235 }
236