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