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  #include "wlan_ll_sap_api.h"
18  #include <../../core/src/wlan_ll_lt_sap_bearer_switch.h>
19  #include <../../core/src/wlan_ll_lt_sap_main.h>
20  #include "wlan_cm_api.h"
21  #include "wlan_policy_mgr_ll_sap.h"
22  #include "wlan_policy_mgr_api.h"
23  #include "wlan_reg_services_api.h"
24  #include "wlan_dfs_utils_api.h"
25  #include "wlan_mlme_main.h"
26  
27  #ifdef WLAN_FEATURE_BEARER_SWITCH
28  wlan_bs_req_id
wlan_ll_lt_sap_bearer_switch_get_id(struct wlan_objmgr_psoc * psoc)29  wlan_ll_lt_sap_bearer_switch_get_id(struct wlan_objmgr_psoc *psoc)
30  {
31  	return ll_lt_sap_bearer_switch_get_id(psoc);
32  }
33  
34  QDF_STATUS
wlan_ll_lt_sap_switch_bearer_to_ble(struct wlan_objmgr_psoc * psoc,struct wlan_bearer_switch_request * bs_request)35  wlan_ll_lt_sap_switch_bearer_to_ble(struct wlan_objmgr_psoc *psoc,
36  				struct wlan_bearer_switch_request *bs_request)
37  {
38  	return ll_lt_sap_switch_bearer_to_ble(psoc, bs_request);
39  }
40  
41  static void
connect_start_bearer_switch_requester_cb(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,wlan_bs_req_id request_id,QDF_STATUS status,uint32_t req_value,void * request_params)42  connect_start_bearer_switch_requester_cb(struct wlan_objmgr_psoc *psoc,
43  					 uint8_t vdev_id,
44  					 wlan_bs_req_id request_id,
45  					 QDF_STATUS status, uint32_t req_value,
46  					 void *request_params)
47  {
48  	wlan_cm_id cm_id = req_value;
49  
50  	wlan_cm_bearer_switch_resp(psoc, vdev_id, cm_id, status);
51  }
52  
53  QDF_STATUS
wlan_ll_sap_switch_bearer_on_sta_connect_start(struct wlan_objmgr_psoc * psoc,qdf_list_t * scan_list,uint8_t vdev_id,wlan_cm_id cm_id)54  wlan_ll_sap_switch_bearer_on_sta_connect_start(struct wlan_objmgr_psoc *psoc,
55  					       qdf_list_t *scan_list,
56  					       uint8_t vdev_id,
57  					       wlan_cm_id cm_id)
58  {
59  	struct scan_cache_node *scan_node = NULL;
60  	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
61  	uint32_t ch_freq = 0;
62  	struct scan_cache_entry *entry;
63  	struct wlan_objmgr_vdev *vdev;
64  	struct wlan_bearer_switch_request bs_request = {0};
65  	qdf_freq_t ll_lt_sap_freq;
66  	bool is_bearer_switch_required = false;
67  	QDF_STATUS status = QDF_STATUS_E_ALREADY;
68  	uint8_t ll_lt_sap_vdev_id;
69  
70  	ll_lt_sap_vdev_id = wlan_policy_mgr_get_ll_lt_sap_vdev_id(psoc);
71  	/* LL_LT SAP is not present, bearer switch is not required */
72  	if (ll_lt_sap_vdev_id == WLAN_INVALID_VDEV_ID)
73  		return status;
74  	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, ll_lt_sap_vdev_id,
75  						    WLAN_LL_SAP_ID);
76  	if (!vdev)
77  		return status;
78  
79  	if (!scan_list || !qdf_list_size(scan_list))
80  		goto rel_ref;
81  
82  	ll_lt_sap_freq = policy_mgr_get_ll_lt_sap_freq(psoc);
83  	qdf_list_peek_front(scan_list, &cur_node);
84  
85  	while (cur_node) {
86  		qdf_list_peek_next(scan_list, cur_node, &next_node);
87  
88  		scan_node = qdf_container_of(cur_node, struct scan_cache_node,
89  					     node);
90  		entry = scan_node->entry;
91  		ch_freq = entry->channel.chan_freq;
92  
93  		/*
94  		 * Switch the bearer in case of SCC/MCC for LL_LT SAP
95  		 */
96  		if (policy_mgr_2_freq_always_on_same_mac(psoc, ch_freq,
97  							 ll_lt_sap_freq)) {
98  			ll_sap_debug("Scan list has BSS of freq %d on same mac with ll_lt sap %d",
99  				     ch_freq, ll_lt_sap_freq);
100  			is_bearer_switch_required = true;
101  			break;
102  		}
103  
104  		ch_freq = 0;
105  		cur_node = next_node;
106  		next_node = NULL;
107  	}
108  
109  	if (!is_bearer_switch_required)
110  		goto rel_ref;
111  
112  	bs_request.vdev_id = vdev_id;
113  	bs_request.request_id = ll_lt_sap_bearer_switch_get_id(psoc);
114  	bs_request.req_type = WLAN_BS_REQ_TO_NON_WLAN;
115  	bs_request.source = BEARER_SWITCH_REQ_CONNECT;
116  	bs_request.requester_cb = connect_start_bearer_switch_requester_cb;
117  	bs_request.arg_value = cm_id;
118  
119  	status = ll_lt_sap_switch_bearer_to_ble(psoc, &bs_request);
120  
121  	if (QDF_IS_STATUS_ERROR(status))
122  		status = QDF_STATUS_E_ALREADY;
123  rel_ref:
124  	wlan_objmgr_vdev_release_ref(vdev, WLAN_LL_SAP_ID);
125  
126  	return status;
127  }
128  
connect_complete_bearer_switch_requester_cb(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,wlan_bs_req_id request_id,QDF_STATUS status,uint32_t req_value,void * request_params)129  static void connect_complete_bearer_switch_requester_cb(
130  						struct wlan_objmgr_psoc *psoc,
131  						uint8_t vdev_id,
132  						wlan_bs_req_id request_id,
133  						QDF_STATUS status,
134  						uint32_t req_value,
135  						void *request_params)
136  {
137  	/* Drop this response as no action is required */
138  }
139  
wlan_ll_sap_switch_bearer_on_sta_connect_complete(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id)140  QDF_STATUS wlan_ll_sap_switch_bearer_on_sta_connect_complete(
141  						struct wlan_objmgr_psoc *psoc,
142  						uint8_t vdev_id)
143  {
144  	struct wlan_bearer_switch_request bs_request = {0};
145  	QDF_STATUS status;
146  
147  	bs_request.vdev_id = vdev_id;
148  	bs_request.request_id = ll_lt_sap_bearer_switch_get_id(psoc);
149  	bs_request.req_type = WLAN_BS_REQ_TO_WLAN;
150  	bs_request.source = BEARER_SWITCH_REQ_CONNECT;
151  	bs_request.requester_cb = connect_complete_bearer_switch_requester_cb;
152  
153  	status = ll_lt_sap_switch_bearer_to_wlan(psoc, &bs_request);
154  
155  	if (QDF_IS_STATUS_ERROR(status))
156  		return QDF_STATUS_E_ALREADY;
157  
158  	return QDF_STATUS_SUCCESS;
159  }
160  #endif
161  
wlan_ll_lt_sap_get_freq_list(struct wlan_objmgr_psoc * psoc,struct wlan_ll_lt_sap_freq_list * freq_list,uint8_t vdev_id)162  QDF_STATUS wlan_ll_lt_sap_get_freq_list(
163  				struct wlan_objmgr_psoc *psoc,
164  				struct wlan_ll_lt_sap_freq_list *freq_list,
165  				uint8_t vdev_id)
166  {
167  	return ll_lt_sap_get_freq_list(psoc, freq_list, vdev_id);
168  }
169  
wlan_ll_lt_sap_override_freq(struct wlan_objmgr_psoc * psoc,uint32_t vdev_id,qdf_freq_t chan_freq)170  qdf_freq_t wlan_ll_lt_sap_override_freq(struct wlan_objmgr_psoc *psoc,
171  					uint32_t vdev_id,
172  					qdf_freq_t chan_freq)
173  {
174  	qdf_freq_t freq;
175  
176  	if (!policy_mgr_is_vdev_ll_lt_sap(psoc, vdev_id))
177  		return chan_freq;
178  
179  	/*
180  	 * If already any concurrent interface is present on this frequency,
181  	 * select a different frequency to start ll_lt_sap
182  	 */
183  	if (!policy_mgr_get_connection_count_with_ch_freq(chan_freq))
184  		return chan_freq;
185  
186  	freq = ll_lt_sap_get_valid_freq(psoc, vdev_id);
187  
188  	ll_sap_debug("Vdev %d ll_lt_sap old freq %d new freq %d", vdev_id,
189  		     chan_freq, freq);
190  
191  	return freq;
192  }
193  
wlan_get_ll_lt_sap_restart_freq(struct wlan_objmgr_pdev * pdev,qdf_freq_t chan_freq,uint8_t vdev_id,enum sap_csa_reason_code * csa_reason)194  qdf_freq_t wlan_get_ll_lt_sap_restart_freq(struct wlan_objmgr_pdev *pdev,
195  					   qdf_freq_t chan_freq,
196  					   uint8_t vdev_id,
197  					   enum sap_csa_reason_code *csa_reason)
198  {
199  	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
200  	qdf_freq_t restart_freq;
201  
202  	if (wlan_reg_is_disable_in_secondary_list_for_freq(pdev, chan_freq) &&
203  	    !utils_dfs_is_freq_in_nol(pdev, chan_freq)) {
204  		*csa_reason = CSA_REASON_CHAN_DISABLED;
205  		goto get_new_ll_lt_sap_freq;
206  	} else if (wlan_reg_is_passive_for_freq(pdev, chan_freq))  {
207  		*csa_reason = CSA_REASON_CHAN_PASSIVE;
208  		goto get_new_ll_lt_sap_freq;
209  	} else if (!policy_mgr_is_sap_freq_allowed(psoc,
210  				wlan_get_opmode_from_vdev_id(pdev, vdev_id),
211  				chan_freq)) {
212  		*csa_reason = CSA_REASON_UNSAFE_CHANNEL;
213  		goto get_new_ll_lt_sap_freq;
214  	} else if (policy_mgr_is_ll_lt_sap_restart_required(psoc)) {
215  		*csa_reason = CSA_REASON_CONCURRENT_STA_CHANGED_CHANNEL;
216  		goto get_new_ll_lt_sap_freq;
217  	}
218  
219  	return chan_freq;
220  
221  get_new_ll_lt_sap_freq:
222  	restart_freq = ll_lt_sap_get_valid_freq(psoc, vdev_id);
223  
224  	ll_sap_debug("vdev %d old freq %d restart freq %d CSA reason %d ",
225  		     vdev_id, chan_freq, restart_freq, *csa_reason);
226  	return restart_freq;
227  }
228  
fw_bearer_switch_requester_cb(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,wlan_bs_req_id request_id,QDF_STATUS status,uint32_t req_value,void * request_params)229  static void fw_bearer_switch_requester_cb(struct wlan_objmgr_psoc *psoc,
230  					  uint8_t vdev_id,
231  					  wlan_bs_req_id request_id,
232  					  QDF_STATUS status,
233  					  uint32_t req_value,
234  					  void *request_params)
235  {
236  	/*
237  	 * Drop this response as all the responses to the FW is always
238  	 * forwarded
239  	 */
240  }
241  
242  QDF_STATUS
wlan_ll_sap_fw_bearer_switch_req(struct wlan_objmgr_psoc * psoc,enum bearer_switch_req_type req_type)243  wlan_ll_sap_fw_bearer_switch_req(struct wlan_objmgr_psoc *psoc,
244  				 enum bearer_switch_req_type req_type)
245  {
246  	struct wlan_bearer_switch_request bs_request = {0};
247  	QDF_STATUS status;
248  	uint8_t ll_lt_sap_vdev_id;
249  
250  	ll_lt_sap_vdev_id = wlan_policy_mgr_get_ll_lt_sap_vdev_id(psoc);
251  
252  	bs_request.vdev_id = ll_lt_sap_vdev_id;
253  	bs_request.request_id = ll_lt_sap_bearer_switch_get_id(psoc);
254  	bs_request.req_type = req_type;
255  	bs_request.source = BEARER_SWITCH_REQ_FW;
256  	bs_request.requester_cb = fw_bearer_switch_requester_cb;
257  
258  	if (req_type == WLAN_BS_REQ_TO_WLAN)
259  		status = ll_lt_sap_switch_bearer_to_wlan(psoc, &bs_request);
260  
261  	else
262  		status = ll_lt_sap_switch_bearer_to_ble(psoc, &bs_request);
263  
264  	if (QDF_IS_STATUS_ERROR(status))
265  		return QDF_STATUS_E_ALREADY;
266  
267  	return QDF_STATUS_SUCCESS;
268  }
269