1 /* 2 * Copyright (c) 2021, The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 /** 19 * DOC: wlan_mgmt_txrx_rx_re_tgt_api.c 20 * This file contains mgmt rx re-ordering tgt layer related function 21 * definitions 22 */ 23 #include <wlan_mgmt_txrx_rx_reo_tgt_api.h> 24 #include <wlan_mlo_mgr_cmn.h> 25 #include "../../core/src/wlan_mgmt_txrx_rx_reo_i.h" 26 #include <../../core/src/wlan_mgmt_txrx_main_i.h> 27 28 QDF_STATUS 29 tgt_mgmt_rx_reo_get_num_active_hw_links(struct wlan_objmgr_psoc *psoc, 30 int8_t *num_active_hw_links) 31 { 32 struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_txops; 33 34 mgmt_rx_reo_txops = wlan_psoc_get_mgmt_rx_reo_txops(psoc); 35 if (!mgmt_rx_reo_txops) { 36 mgmt_rx_reo_err("mgmt rx reo txops is NULL"); 37 return QDF_STATUS_E_NULL_VALUE; 38 } 39 40 if (!mgmt_rx_reo_txops->get_num_active_hw_links) { 41 mgmt_rx_reo_err("get num active hw links txops is NULL"); 42 return QDF_STATUS_E_NULL_VALUE; 43 } 44 45 return mgmt_rx_reo_txops->get_num_active_hw_links(psoc, 46 num_active_hw_links); 47 } 48 49 QDF_STATUS 50 tgt_mgmt_rx_reo_get_valid_hw_link_bitmap(struct wlan_objmgr_psoc *psoc, 51 uint16_t *valid_hw_link_bitmap) 52 { 53 struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_txops; 54 55 mgmt_rx_reo_txops = wlan_psoc_get_mgmt_rx_reo_txops(psoc); 56 if (!mgmt_rx_reo_txops) { 57 mgmt_rx_reo_err("mgmt rx reo txops is NULL"); 58 return QDF_STATUS_E_NULL_VALUE; 59 } 60 61 if (!mgmt_rx_reo_txops->get_valid_hw_link_bitmap) { 62 mgmt_rx_reo_err("get valid hw link bitmap txops is NULL"); 63 return QDF_STATUS_E_NULL_VALUE; 64 } 65 66 return mgmt_rx_reo_txops->get_valid_hw_link_bitmap(psoc, 67 valid_hw_link_bitmap); 68 } 69 70 QDF_STATUS 71 tgt_mgmt_rx_reo_read_snapshot( 72 struct wlan_objmgr_pdev *pdev, 73 struct mgmt_rx_reo_snapshot_info *snapshot_info, 74 enum mgmt_rx_reo_shared_snapshot_id id, 75 struct mgmt_rx_reo_snapshot_params *value, 76 struct mgmt_rx_reo_shared_snapshot (*raw_snapshot) 77 [MGMT_RX_REO_SNAPSHOT_B2B_READ_SWAR_RETRY_LIMIT]) 78 { 79 struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_txops; 80 81 mgmt_rx_reo_txops = wlan_pdev_get_mgmt_rx_reo_txops(pdev); 82 if (!mgmt_rx_reo_txops) { 83 mgmt_rx_reo_err("mgmt rx reo txops is NULL"); 84 return QDF_STATUS_E_INVAL; 85 } 86 87 if (!mgmt_rx_reo_txops->read_mgmt_rx_reo_snapshot) { 88 mgmt_rx_reo_err("mgmt rx reo read snapshot txops is NULL"); 89 return QDF_STATUS_E_NULL_VALUE; 90 } 91 92 return mgmt_rx_reo_txops->read_mgmt_rx_reo_snapshot(pdev, snapshot_info, 93 id, value, 94 raw_snapshot); 95 } 96 97 /** 98 * tgt_mgmt_rx_reo_enter_algo_without_buffer() - Entry point to the MGMT Rx REO 99 * algorithm when there is no frame buffer 100 * @pdev: pdev for which this frame/event is intended 101 * @reo_params: MGMT Rx REO parameters corresponding to this frame/event 102 * @type: Type of the MGMT Rx REO frame/event descriptor 103 * 104 * Return: QDF_STATUS of operation 105 */ 106 static QDF_STATUS 107 tgt_mgmt_rx_reo_enter_algo_without_buffer( 108 struct wlan_objmgr_pdev *pdev, 109 struct mgmt_rx_reo_params *reo_params, 110 enum mgmt_rx_reo_frame_descriptor_type type) 111 { 112 struct mgmt_rx_event_params mgmt_rx_params = {0}; 113 struct mgmt_rx_reo_frame_descriptor desc = {0}; 114 bool is_frm_queued; 115 QDF_STATUS status; 116 int8_t link_id; 117 uint8_t ml_grp_id; 118 119 if (!pdev) { 120 mgmt_rx_reo_err("pdev is null"); 121 return QDF_STATUS_E_NULL_VALUE; 122 } 123 124 if (!wlan_mgmt_rx_reo_is_feature_enabled_at_pdev(pdev)) 125 return QDF_STATUS_SUCCESS; 126 127 if (!reo_params) { 128 mgmt_rx_reo_err("mgmt rx reo params are null"); 129 return QDF_STATUS_E_NULL_VALUE; 130 } 131 132 link_id = wlan_get_mlo_link_id_from_pdev(pdev); 133 if (link_id < 0) { 134 mgmt_rx_reo_err("Invalid link %d for the pdev", link_id); 135 return QDF_STATUS_E_INVAL; 136 } 137 138 if (!reo_params->valid) { 139 mgmt_rx_reo_err_rl("Invalid MGMT rx REO param for link %u", 140 link_id); 141 return QDF_STATUS_E_INVAL; 142 } 143 144 ml_grp_id = wlan_get_mlo_grp_id_from_pdev(pdev); 145 if (ml_grp_id > WLAN_MAX_MLO_GROUPS) { 146 mgmt_rx_reo_err("Invalid MLO Group %d for the pdev", 147 ml_grp_id); 148 return QDF_STATUS_E_INVAL; 149 } 150 151 reo_params->link_id = link_id; 152 reo_params->mlo_grp_id = ml_grp_id; 153 mgmt_rx_params.reo_params = reo_params; 154 155 desc.nbuf = NULL; /* No frame buffer */ 156 desc.rx_params = &mgmt_rx_params; 157 desc.type = type; 158 desc.ingress_timestamp = qdf_get_log_timestamp(); 159 desc.ingress_list_size_rx = -1; 160 desc.ingress_list_insertion_pos = -1; 161 desc.egress_list_size_rx = -1; 162 desc.egress_list_insertion_pos = -1; 163 desc.frame_type = IEEE80211_FC0_TYPE_MGT; 164 desc.frame_subtype = 0xFF; 165 desc.reo_required = is_mgmt_rx_reo_required(pdev, &desc); 166 desc.queued_list = MGMT_RX_REO_LIST_TYPE_INVALID; 167 168 /* Enter the REO algorithm */ 169 status = wlan_mgmt_rx_reo_algo_entry(pdev, &desc, &is_frm_queued); 170 171 qdf_assert_always(!is_frm_queued); 172 173 return status; 174 } 175 176 QDF_STATUS 177 tgt_mgmt_rx_reo_fw_consumed_event_handler(struct wlan_objmgr_pdev *pdev, 178 struct mgmt_rx_reo_params *params) 179 { 180 return tgt_mgmt_rx_reo_enter_algo_without_buffer( 181 pdev, params, MGMT_RX_REO_FRAME_DESC_FW_CONSUMED_FRAME); 182 } 183 184 QDF_STATUS 185 tgt_mgmt_rx_reo_host_drop_handler(struct wlan_objmgr_pdev *pdev, 186 struct mgmt_rx_reo_params *params) 187 { 188 return tgt_mgmt_rx_reo_enter_algo_without_buffer( 189 pdev, params, MGMT_RX_REO_FRAME_DESC_ERROR_FRAME); 190 } 191 192 QDF_STATUS tgt_mgmt_rx_reo_filter_config(struct wlan_objmgr_pdev *pdev, 193 struct mgmt_rx_reo_filter *filter) 194 { 195 struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_txops; 196 197 mgmt_rx_reo_txops = wlan_pdev_get_mgmt_rx_reo_txops(pdev); 198 if (!mgmt_rx_reo_txops) { 199 mgmt_rx_reo_err("MGMT Rx REO txops is NULL"); 200 return QDF_STATUS_E_NULL_VALUE; 201 } 202 203 if (!mgmt_rx_reo_txops->mgmt_rx_reo_filter_config) { 204 mgmt_rx_reo_err("mgmt_rx_reo_filter_config is NULL"); 205 return QDF_STATUS_E_NULL_VALUE; 206 } 207 208 return mgmt_rx_reo_txops->mgmt_rx_reo_filter_config(pdev, filter); 209 } 210 211 QDF_STATUS 212 tgt_mgmt_rx_reo_get_snapshot_info 213 (struct wlan_objmgr_pdev *pdev, 214 enum mgmt_rx_reo_shared_snapshot_id id, 215 struct mgmt_rx_reo_snapshot_info *snapshot_info) 216 { 217 struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_txops; 218 219 mgmt_rx_reo_txops = wlan_pdev_get_mgmt_rx_reo_txops(pdev); 220 if (!mgmt_rx_reo_txops) { 221 mgmt_rx_reo_err("mgmt rx reo txops is NULL"); 222 return QDF_STATUS_E_NULL_VALUE; 223 } 224 225 if (!mgmt_rx_reo_txops->get_mgmt_rx_reo_snapshot_info) { 226 mgmt_rx_reo_err("txops entry for get snapshot info is null"); 227 return QDF_STATUS_E_NULL_VALUE; 228 } 229 230 return mgmt_rx_reo_txops->get_mgmt_rx_reo_snapshot_info(pdev, id, 231 snapshot_info); 232 } 233 234 bool 235 wlan_mgmt_rx_reo_check_simulation_in_progress(struct wlan_objmgr_pdev *pdev) 236 { 237 uint8_t ml_grp_id; 238 struct wlan_objmgr_psoc *psoc; 239 240 psoc = wlan_pdev_get_psoc(pdev); 241 if (!psoc) 242 return false; 243 244 if (!wlan_mlo_get_psoc_capable(psoc)) 245 return false; 246 247 ml_grp_id = wlan_get_mlo_grp_id_from_pdev(pdev); 248 if (ml_grp_id > WLAN_MAX_MLO_GROUPS) { 249 mgmt_rx_reo_err("INVALID ML Group ID for the PDEV"); 250 return false; 251 } 252 253 if (!wlan_mgmt_rx_reo_is_simulation_in_progress(ml_grp_id)) 254 return false; 255 256 return true; 257 } 258 259 QDF_STATUS tgt_mgmt_rx_reo_frame_handler( 260 struct wlan_objmgr_pdev *pdev, 261 qdf_nbuf_t buf, 262 struct mgmt_rx_event_params *mgmt_rx_params) 263 { 264 QDF_STATUS status; 265 struct mgmt_rx_reo_frame_descriptor desc = {0}; 266 bool is_queued; 267 int8_t link_id; 268 uint8_t ml_grp_id; 269 uint8_t frame_type; 270 uint8_t frame_subtype; 271 struct ieee80211_frame *wh; 272 273 if (!pdev) { 274 mgmt_rx_reo_err("pdev is NULL"); 275 status = QDF_STATUS_E_NULL_VALUE; 276 goto cleanup; 277 } 278 279 if (!wlan_mgmt_rx_reo_check_simulation_in_progress(pdev) && !buf) { 280 mgmt_rx_reo_err("nbuf is NULL"); 281 status = QDF_STATUS_E_NULL_VALUE; 282 goto cleanup; 283 } 284 285 if (!mgmt_rx_params) { 286 mgmt_rx_reo_err("MGMT rx params is NULL"); 287 status = QDF_STATUS_E_NULL_VALUE; 288 goto cleanup; 289 } 290 291 if (!wlan_mgmt_rx_reo_is_feature_enabled_at_pdev(pdev)) 292 return tgt_mgmt_txrx_process_rx_frame(pdev, buf, 293 mgmt_rx_params); 294 295 if (!mgmt_rx_params->reo_params) { 296 mgmt_rx_reo_err("MGMT rx REO params is NULL"); 297 status = QDF_STATUS_E_NULL_VALUE; 298 goto cleanup; 299 } 300 301 link_id = wlan_get_mlo_link_id_from_pdev(pdev); 302 if (link_id < 0) { 303 mgmt_rx_reo_err("Invalid link %d for the pdev", link_id); 304 status = QDF_STATUS_E_INVAL; 305 goto cleanup; 306 } 307 308 if (!mgmt_rx_params->reo_params->valid) { 309 mgmt_rx_reo_err_rl("Invalid MGMT rx REO param for link %u", 310 link_id); 311 status = QDF_STATUS_E_INVAL; 312 goto cleanup; 313 } 314 315 ml_grp_id = wlan_get_mlo_grp_id_from_pdev(pdev); 316 if (ml_grp_id > WLAN_MAX_MLO_GROUPS) { 317 mgmt_rx_reo_err("Invalid MGMT rx reo Group id"); 318 status = QDF_STATUS_E_INVAL; 319 goto cleanup; 320 } 321 322 mgmt_rx_params->reo_params->link_id = link_id; 323 mgmt_rx_params->reo_params->mlo_grp_id = ml_grp_id; 324 325 /* Populate frame descriptor */ 326 desc.type = MGMT_RX_REO_FRAME_DESC_HOST_CONSUMED_FRAME; 327 desc.nbuf = buf; 328 desc.rx_params = mgmt_rx_params; 329 desc.ingress_timestamp = qdf_get_log_timestamp(); 330 desc.ingress_list_size_rx = -1; 331 desc.ingress_list_insertion_pos = -1; 332 desc.egress_list_size_rx = -1; 333 desc.egress_list_insertion_pos = -1; 334 desc.queued_list = MGMT_RX_REO_LIST_TYPE_INVALID; 335 336 wh = (struct ieee80211_frame *)qdf_nbuf_data(buf); 337 frame_type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; 338 frame_subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; 339 340 desc.frame_type = frame_type; 341 desc.frame_subtype = frame_subtype; 342 343 if (frame_type != IEEE80211_FC0_TYPE_MGT || 344 !is_mgmt_rx_reo_required(pdev, &desc)) { 345 desc.reo_required = false; 346 status = wlan_mgmt_rx_reo_algo_entry(pdev, &desc, &is_queued); 347 348 if (QDF_IS_STATUS_ERROR(status)) { 349 mgmt_rx_reo_err_rl("Failed to execute REO algorithm"); 350 goto cleanup; 351 } 352 353 qdf_assert_always(!is_queued); 354 355 return tgt_mgmt_txrx_process_rx_frame(pdev, buf, 356 mgmt_rx_params); 357 } else { 358 desc.reo_required = true; 359 status = wlan_mgmt_rx_reo_algo_entry(pdev, &desc, &is_queued); 360 361 if (QDF_IS_STATUS_ERROR(status)) 362 mgmt_rx_reo_err_rl("Failed to execute REO algorithm"); 363 364 /** 365 * If frame is queued, we shouldn't free up params and 366 * buf pointers. 367 */ 368 if (is_queued) 369 return status; 370 } 371 cleanup: 372 qdf_nbuf_free(buf); 373 free_mgmt_rx_event_params(mgmt_rx_params); 374 375 return status; 376 } 377