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