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