1 /*
2  * Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 /**
18  * DOC: contains policy manager ll_sap definitions specific to the ll_sap module
19  */
20 
21 #include "wlan_policy_mgr_ll_sap.h"
22 #include "wlan_policy_mgr_public_struct.h"
23 #include "wlan_policy_mgr_api.h"
24 #include "wlan_policy_mgr_i.h"
25 #include "wlan_cmn.h"
26 #include "wlan_ll_sap_api.h"
27 
policy_mgr_ll_lt_sap_get_valid_freq(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_pdev * pdev,uint8_t vdev_id,qdf_freq_t sap_ch_freq,uint8_t cc_switch_mode,qdf_freq_t * new_sap_freq,bool * is_ll_lt_sap_present)28 void policy_mgr_ll_lt_sap_get_valid_freq(struct wlan_objmgr_psoc *psoc,
29 					 struct wlan_objmgr_pdev *pdev,
30 					 uint8_t vdev_id,
31 					 qdf_freq_t sap_ch_freq,
32 					 uint8_t cc_switch_mode,
33 					 qdf_freq_t *new_sap_freq,
34 					 bool *is_ll_lt_sap_present)
35 {
36 	enum sap_csa_reason_code csa_reason;
37 	enum policy_mgr_con_mode conn_mode;
38 	qdf_freq_t ll_lt_sap_freq = 0;
39 	*is_ll_lt_sap_present = false;
40 
41 	/* If Vdev is ll_lt_sap, check if the frequency on which it is
42 	 * coming up is correct, else, get new frequency
43 	 */
44 	if (policy_mgr_is_vdev_ll_lt_sap(psoc, vdev_id)) {
45 		*new_sap_freq = wlan_get_ll_lt_sap_restart_freq(pdev,
46 								sap_ch_freq,
47 								vdev_id,
48 								&csa_reason);
49 		*is_ll_lt_sap_present = true;
50 	}
51 
52 	ll_lt_sap_freq = policy_mgr_get_ll_lt_sap_freq(psoc);
53 	if (!ll_lt_sap_freq)
54 		return;
55 
56 	conn_mode = policy_mgr_get_mode_by_vdev_id(psoc, vdev_id);
57 
58 	if (conn_mode == PM_SAP_MODE) {
59 		/* If ll_lt_sap and concurrent SAP are on same MAC,
60 		 * update the frequency of concurrent SAP, else return.
61 		 */
62 		if (!policy_mgr_are_2_freq_on_same_mac(psoc, sap_ch_freq,
63 						       ll_lt_sap_freq))
64 			return;
65 		goto policy_mgr_check_scc;
66 	} else if (conn_mode == PM_P2P_GO_MODE) {
67 		/* If ll_lt_sap and P2P_GO are in SCC,
68 		 * update the frequency of concurrent GO else, return.
69 		 */
70 		if (ll_lt_sap_freq != sap_ch_freq)
71 			return;
72 		goto policy_mgr_check_scc;
73 	} else {
74 		policy_mgr_debug("Invalid con mode %d vdev %d", conn_mode,
75 				 vdev_id);
76 		return;
77 	}
78 
79 policy_mgr_check_scc:
80 	policy_mgr_check_scc_channel(psoc, new_sap_freq, sap_ch_freq, vdev_id,
81 				     cc_switch_mode);
82 	policy_mgr_debug("vdev_id %d old_freq %d new_freq %d", vdev_id,
83 			 sap_ch_freq, *new_sap_freq);
84 }
85 
wlan_policy_mgr_get_ll_lt_sap_vdev_id(struct wlan_objmgr_psoc * psoc)86 uint8_t wlan_policy_mgr_get_ll_lt_sap_vdev_id(struct wlan_objmgr_psoc *psoc)
87 {
88 	uint8_t ll_lt_sap_cnt;
89 	uint8_t vdev_id_list[MAX_NUMBER_OF_CONC_CONNECTIONS];
90 
91 	ll_lt_sap_cnt = policy_mgr_get_mode_specific_conn_info(psoc, NULL,
92 							vdev_id_list,
93 							PM_LL_LT_SAP_MODE);
94 
95 	/* Currently only 1 ll_lt_sap is supported */
96 	if (!ll_lt_sap_cnt)
97 		return WLAN_INVALID_VDEV_ID;
98 
99 	return vdev_id_list[0];
100 }
101 
__policy_mgr_is_ll_lt_sap_restart_required(struct wlan_objmgr_psoc * psoc,const char * func)102 bool __policy_mgr_is_ll_lt_sap_restart_required(struct wlan_objmgr_psoc *psoc,
103 						const char *func)
104 {
105 	qdf_freq_t ll_lt_sap_freq = 0;
106 	uint8_t scc_vdev_id;
107 	bool is_scc = false;
108 	uint8_t conn_idx = 0;
109 	struct policy_mgr_psoc_priv_obj *pm_ctx;
110 
111 	pm_ctx = policy_mgr_get_context(psoc);
112 	if (!pm_ctx) {
113 		policy_mgr_err("Invalid pm ctx");
114 		return false;
115 	}
116 
117 	ll_lt_sap_freq = policy_mgr_get_ll_lt_sap_freq(psoc);
118 
119 	if (!ll_lt_sap_freq)
120 		return false;
121 
122 	/*
123 	 * Restart ll_lt_sap if any other interface is present in SCC
124 	 * with LL_LT_SAP.
125 	 */
126 	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
127 	for (conn_idx = 0; conn_idx < MAX_NUMBER_OF_CONC_CONNECTIONS;
128 	     conn_idx++) {
129 		if (pm_conc_connection_list[conn_idx].mode ==
130 		      PM_LL_LT_SAP_MODE)
131 			continue;
132 
133 		if (ll_lt_sap_freq == pm_conc_connection_list[conn_idx].freq) {
134 			scc_vdev_id = pm_conc_connection_list[conn_idx].vdev_id;
135 			is_scc = true;
136 			break;
137 		}
138 	}
139 	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
140 
141 	if (is_scc) {
142 		uint8_t ll_lt_sap_vdev_id =
143 				wlan_policy_mgr_get_ll_lt_sap_vdev_id(psoc);
144 
145 		policymgr_nofl_debug("%s ll_lt_sap vdev %d with freq %d is in scc with vdev %d",
146 				     func, ll_lt_sap_vdev_id, ll_lt_sap_freq,
147 				     scc_vdev_id);
148 		return true;
149 	}
150 
151 	return false;
152 }
153 
154 /**
155  * policy_mgr_ll_lt_sap_get_restart_freq_for_concurent_sap() - Get restart frequency
156  * for concurrent SAP which is in concurrency with LL_LT_SAP
157  * @pm_ctx: Policy manager context
158  * @vdev_id: Vdev id of the SAP for which restart freq is required
159  * @curr_freq: Current frequency of the SAP for which restart freq is required
160  * @ll_lt_sap_enabled: Indicates if ll_lt_sap is getting enabled or disabled
161  *
162  * This API returns user configured frequency if ll_lt_sap is going down and
163  * if ll_lt_sap is coming up it returns frequency according to ll_lt_sap
164  * concurrency.
165  *
166  * Return: Restart frequency
167  */
168 static qdf_freq_t
policy_mgr_ll_lt_sap_get_restart_freq_for_concurent_sap(struct policy_mgr_psoc_priv_obj * pm_ctx,uint8_t vdev_id,qdf_freq_t curr_freq,bool ll_lt_sap_enabled)169 policy_mgr_ll_lt_sap_get_restart_freq_for_concurent_sap(
170 					struct policy_mgr_psoc_priv_obj *pm_ctx,
171 					uint8_t vdev_id,
172 					qdf_freq_t curr_freq,
173 					bool ll_lt_sap_enabled)
174 {
175 	qdf_freq_t user_config_freq;
176 	uint8_t i;
177 	QDF_STATUS status;
178 	uint32_t channel_list[NUM_CHANNELS];
179 	uint32_t num_channels;
180 	qdf_freq_t restart_freq = 0;
181 
182 	/*
183 	 * If ll_lt_sap is getting disabled, return user configured frequency
184 	 * for concurrent SAP restart, if user configured frequency is not valid
185 	 * frequency, remain on the same frequency and do not restart the SAP
186 	 */
187 	if (!ll_lt_sap_enabled) {
188 		user_config_freq = policy_mgr_get_user_config_sap_freq(
189 								pm_ctx->psoc,
190 								vdev_id);
191 		if (wlan_reg_is_enable_in_secondary_list_for_freq(
192 							pm_ctx->pdev,
193 							user_config_freq) &&
194 		    policy_mgr_is_safe_channel(pm_ctx->psoc, user_config_freq))
195 			return user_config_freq;
196 		return curr_freq;
197 	}
198 
199 	status = policy_mgr_get_valid_chans(pm_ctx->psoc, channel_list,
200 					    &num_channels);
201 	if (QDF_IS_STATUS_ERROR(status)) {
202 		policy_mgr_err("Error in getting valid channels");
203 		return curr_freq;
204 	}
205 
206 	/* return first valid 2.4 GHz frequency */
207 	for (i = 0; i < num_channels; i++) {
208 		if (wlan_reg_is_24ghz_ch_freq(channel_list[i])) {
209 			if (!restart_freq)
210 				restart_freq = channel_list[i];
211 			/* Prefer SCC frequency */
212 			if (policy_mgr_get_connection_count_with_ch_freq(
213 							channel_list[i])) {
214 				restart_freq = channel_list[i];
215 				break;
216 			}
217 		}
218 	}
219 	return restart_freq;
220 }
221 
policy_mgr_ll_lt_sap_restart_concurrent_sap(struct wlan_objmgr_psoc * psoc,bool is_ll_lt_sap_enabled)222 void policy_mgr_ll_lt_sap_restart_concurrent_sap(struct wlan_objmgr_psoc *psoc,
223 						 bool is_ll_lt_sap_enabled)
224 {
225 	struct policy_mgr_psoc_priv_obj *pm_ctx;
226 	struct policy_mgr_conc_connection_info sap_info = {0};
227 	qdf_freq_t restart_freq;
228 	struct ch_params ch_params = {0};
229 	uint8_t i;
230 	enum sap_csa_reason_code csa_reason;
231 
232 	pm_ctx = policy_mgr_get_context(psoc);
233 	if (!pm_ctx) {
234 		policy_mgr_err("Invalid pm context");
235 		return;
236 	}
237 
238 	qdf_mem_zero(&sap_info, sizeof(sap_info));
239 
240 	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
241 	for (i = 0; i < MAX_NUMBER_OF_CONC_CONNECTIONS; i++) {
242 		if (!pm_conc_connection_list[i].in_use)
243 			continue;
244 		if (PM_SAP_MODE == pm_conc_connection_list[i].mode ||
245 		    PM_LL_LT_SAP_MODE == pm_conc_connection_list[i].mode) {
246 			qdf_mem_copy(&sap_info, &pm_conc_connection_list[i],
247 				     sizeof(sap_info));
248 			break;
249 		}
250 	}
251 	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
252 
253 	/* No concurrent SAP or ll_lt_sap present, return */
254 	if (!sap_info.in_use)
255 		return;
256 
257 	if (sap_info.mode == PM_SAP_MODE) {
258 		/*
259 		 * For SBS case, no need to restart concurrent SAP as LL_LT_SAP
260 		 * and concurrent SAP can be on different MACs
261 		 */
262 		if (policy_mgr_is_hw_sbs_capable(psoc))
263 			return;
264 
265 		/*
266 		 * If concurrent SAP is 2.4 GHz and ll_lt_sap is getting enabled
267 		 * then there is no need to restart the concurrent SAP
268 		 */
269 		if (is_ll_lt_sap_enabled &&
270 		    wlan_reg_is_24ghz_ch_freq(sap_info.freq))
271 			return;
272 
273 		/*
274 		 * If concurrent SAP is 5 GHz/6 GHz and ll_lt_sap is getting
275 		 * disabled then there is no need to restart the concurrent SAP
276 		 */
277 		else if (!is_ll_lt_sap_enabled &&
278 			 (wlan_reg_is_5ghz_ch_freq(sap_info.freq) ||
279 			 wlan_reg_is_6ghz_chan_freq(sap_info.freq)))
280 			return;
281 
282 		restart_freq =
283 		policy_mgr_ll_lt_sap_get_restart_freq_for_concurent_sap(
284 							pm_ctx,
285 							sap_info.vdev_id,
286 							sap_info.freq,
287 							is_ll_lt_sap_enabled);
288 		csa_reason = CSA_REASON_CONCURRENT_LL_LT_SAP_EVENT;
289 	} else {
290 		restart_freq = wlan_get_ll_lt_sap_restart_freq(pm_ctx->pdev,
291 							       sap_info.freq,
292 							       sap_info.vdev_id,
293 							       &csa_reason);
294 	}
295 
296 	if (pm_ctx->hdd_cbacks.hdd_is_chan_switch_in_progress &&
297 	    pm_ctx->hdd_cbacks.hdd_is_chan_switch_in_progress()) {
298 		policy_mgr_debug("channel switch is already in progress");
299 		return;
300 	}
301 
302 	if (!restart_freq) {
303 		policy_mgr_err("Restart freq not found for vdev %d",
304 			       sap_info.vdev_id);
305 		return;
306 	}
307 	if (restart_freq == sap_info.freq) {
308 		policy_mgr_debug("vdev %d restart freq %d same as current freq",
309 				 sap_info.vdev_id, restart_freq);
310 		return;
311 	}
312 	ch_params.ch_width = policy_mgr_get_ch_width(sap_info.bw);
313 	wlan_reg_set_channel_params_for_pwrmode(pm_ctx->pdev, restart_freq,
314 						0, &ch_params,
315 						REG_CURRENT_PWR_MODE);
316 	policy_mgr_debug("Restart SAP vdev %d with %d freq width %d",
317 			 sap_info.vdev_id, restart_freq, ch_params.ch_width);
318 
319 	if (pm_ctx->hdd_cbacks.wlan_hdd_set_sap_csa_reason)
320 		pm_ctx->hdd_cbacks.wlan_hdd_set_sap_csa_reason(psoc,
321 							       sap_info.vdev_id,
322 							       csa_reason);
323 
324 	policy_mgr_change_sap_channel_with_csa(psoc, sap_info.vdev_id,
325 					       restart_freq,
326 					       ch_params.ch_width, true);
327 }
328