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