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 ml_grp_id = wlan_get_mlo_grp_id_from_pdev(pdev); 139 if (ml_grp_id > WLAN_MAX_MLO_GROUPS) { 140 mgmt_rx_reo_err("Invalid MLO Group %d for the pdev", 141 ml_grp_id); 142 return QDF_STATUS_E_INVAL; 143 } 144 145 reo_params->link_id = link_id; 146 reo_params->mlo_grp_id = ml_grp_id; 147 mgmt_rx_params.reo_params = reo_params; 148 149 desc.nbuf = NULL; /* No frame buffer */ 150 desc.rx_params = &mgmt_rx_params; 151 desc.reo_params_copy = *mgmt_rx_params.reo_params; 152 desc.type = type; 153 desc.ingress_timestamp = qdf_get_log_timestamp(); 154 desc.ingress_list_size_rx = -1; 155 desc.ingress_list_insertion_pos = -1; 156 desc.egress_list_size_rx = -1; 157 desc.egress_list_insertion_pos = -1; 158 desc.frame_type = IEEE80211_FC0_TYPE_MGT; 159 desc.frame_subtype = 0xFF; 160 desc.reo_required = is_mgmt_rx_reo_required(pdev, &desc); 161 desc.queued_list = MGMT_RX_REO_LIST_TYPE_INVALID; 162 desc.drop = false; 163 desc.drop_reason = MGMT_RX_REO_INGRESS_DROP_REASON_INVALID; 164 165 /* Enter the REO algorithm */ 166 status = wlan_mgmt_rx_reo_algo_entry(pdev, &desc, &is_frm_queued); 167 if (QDF_IS_STATUS_ERROR(status)) 168 return status; 169 170 if (is_frm_queued) { 171 mgmt_rx_reo_err("Frame is queued to reo list"); 172 return QDF_STATUS_E_FAILURE; 173 } 174 175 return QDF_STATUS_SUCCESS; 176 } 177 178 QDF_STATUS 179 tgt_mgmt_rx_reo_fw_consumed_event_handler(struct wlan_objmgr_pdev *pdev, 180 struct mgmt_rx_reo_params *params) 181 { 182 return tgt_mgmt_rx_reo_enter_algo_without_buffer( 183 pdev, params, MGMT_RX_REO_FRAME_DESC_FW_CONSUMED_FRAME); 184 } 185 186 QDF_STATUS 187 tgt_mgmt_rx_reo_host_drop_handler(struct wlan_objmgr_pdev *pdev, 188 struct mgmt_rx_reo_params *params) 189 { 190 return tgt_mgmt_rx_reo_enter_algo_without_buffer( 191 pdev, params, MGMT_RX_REO_FRAME_DESC_ERROR_FRAME); 192 } 193 194 /** 195 * psoc_get_hw_link_id_bmap() - Helper API to get HW link ID bitmap of the 196 * pdevs in a psoc 197 * @psoc: Pointer to psoc object 198 * @obj: Pointer to pdev object 199 * @arg: pointer to void * argument 200 * 201 * Return: void 202 */ 203 static void 204 psoc_get_hw_link_id_bmap(struct wlan_objmgr_psoc *psoc, void *obj, void *arg) 205 { 206 struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)obj; 207 uint32_t *link_bitmap = (uint32_t *)arg; 208 int8_t cur_link; 209 210 cur_link = wlan_get_mlo_link_id_from_pdev(pdev); 211 if (cur_link < 0 || cur_link >= MAX_MLO_LINKS) { 212 mgmt_rx_reo_err("Invalid link = %d", cur_link); 213 return; 214 } 215 216 *link_bitmap |= (1 << cur_link); 217 } 218 219 QDF_STATUS 220 tgt_mgmt_rx_reo_release_frames(struct wlan_objmgr_psoc *psoc) 221 { 222 uint8_t mlo_grp_id; 223 uint32_t link_bitmap = 0; 224 225 mlo_grp_id = wlan_mlo_get_psoc_group_id(psoc); 226 227 wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP, 228 psoc_get_hw_link_id_bmap, 229 &link_bitmap, false, WLAN_MGMT_RX_REO_ID); 230 231 return wlan_mgmt_rx_reo_release_frames(mlo_grp_id, link_bitmap); 232 } 233 234 QDF_STATUS tgt_mgmt_rx_reo_filter_config(struct wlan_objmgr_pdev *pdev, 235 struct mgmt_rx_reo_filter *filter) 236 { 237 struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_txops; 238 239 mgmt_rx_reo_txops = wlan_pdev_get_mgmt_rx_reo_txops(pdev); 240 if (!mgmt_rx_reo_txops) { 241 mgmt_rx_reo_err("MGMT Rx REO txops is NULL"); 242 return QDF_STATUS_E_NULL_VALUE; 243 } 244 245 if (!mgmt_rx_reo_txops->mgmt_rx_reo_filter_config) { 246 mgmt_rx_reo_err("mgmt_rx_reo_filter_config is NULL"); 247 return QDF_STATUS_E_NULL_VALUE; 248 } 249 250 return mgmt_rx_reo_txops->mgmt_rx_reo_filter_config(pdev, filter); 251 } 252 253 QDF_STATUS 254 tgt_mgmt_rx_reo_get_snapshot_info 255 (struct wlan_objmgr_pdev *pdev, 256 enum mgmt_rx_reo_shared_snapshot_id id, 257 struct mgmt_rx_reo_snapshot_info *snapshot_info) 258 { 259 struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_txops; 260 261 mgmt_rx_reo_txops = wlan_pdev_get_mgmt_rx_reo_txops(pdev); 262 if (!mgmt_rx_reo_txops) { 263 mgmt_rx_reo_err("mgmt rx reo txops is NULL"); 264 return QDF_STATUS_E_NULL_VALUE; 265 } 266 267 if (!mgmt_rx_reo_txops->get_mgmt_rx_reo_snapshot_info) { 268 mgmt_rx_reo_err("txops entry for get snapshot info is null"); 269 return QDF_STATUS_E_NULL_VALUE; 270 } 271 272 return mgmt_rx_reo_txops->get_mgmt_rx_reo_snapshot_info(pdev, id, 273 snapshot_info); 274 } 275 276 bool 277 wlan_mgmt_rx_reo_check_simulation_in_progress(struct wlan_objmgr_pdev *pdev) 278 { 279 uint8_t ml_grp_id; 280 struct wlan_objmgr_psoc *psoc; 281 282 psoc = wlan_pdev_get_psoc(pdev); 283 if (!psoc) 284 return false; 285 286 if (!wlan_mlo_get_psoc_capable(psoc)) 287 return false; 288 289 ml_grp_id = wlan_get_mlo_grp_id_from_pdev(pdev); 290 if (ml_grp_id > WLAN_MAX_MLO_GROUPS) { 291 mgmt_rx_reo_err("INVALID ML Group ID for the PDEV"); 292 return false; 293 } 294 295 if (!wlan_mgmt_rx_reo_is_simulation_in_progress(ml_grp_id)) 296 return false; 297 298 return true; 299 } 300 301 QDF_STATUS tgt_mgmt_rx_reo_frame_handler( 302 struct wlan_objmgr_pdev *pdev, 303 qdf_nbuf_t buf, 304 struct mgmt_rx_event_params *mgmt_rx_params) 305 { 306 QDF_STATUS status; 307 struct mgmt_rx_reo_frame_descriptor desc = {0}; 308 bool is_queued; 309 int8_t link_id; 310 uint8_t ml_grp_id; 311 uint8_t frame_type; 312 uint8_t frame_subtype; 313 struct ieee80211_frame *wh; 314 315 if (!pdev) { 316 mgmt_rx_reo_err("pdev is NULL"); 317 status = QDF_STATUS_E_NULL_VALUE; 318 goto cleanup; 319 } 320 321 if (!wlan_mgmt_rx_reo_check_simulation_in_progress(pdev) && !buf) { 322 mgmt_rx_reo_err("nbuf is NULL"); 323 status = QDF_STATUS_E_NULL_VALUE; 324 goto cleanup; 325 } 326 327 if (!mgmt_rx_params) { 328 mgmt_rx_reo_err("MGMT rx params is NULL"); 329 status = QDF_STATUS_E_NULL_VALUE; 330 goto cleanup; 331 } 332 333 if (!wlan_mgmt_rx_reo_is_feature_enabled_at_pdev(pdev)) 334 return tgt_mgmt_txrx_process_rx_frame(pdev, buf, 335 mgmt_rx_params); 336 337 if (!mgmt_rx_params->reo_params) { 338 mgmt_rx_reo_err("MGMT rx REO params is NULL"); 339 status = QDF_STATUS_E_NULL_VALUE; 340 goto cleanup; 341 } 342 343 link_id = wlan_get_mlo_link_id_from_pdev(pdev); 344 if (link_id < 0) { 345 mgmt_rx_reo_err("Invalid link %d for the pdev", link_id); 346 status = QDF_STATUS_E_INVAL; 347 goto cleanup; 348 } 349 350 ml_grp_id = wlan_get_mlo_grp_id_from_pdev(pdev); 351 if (ml_grp_id > WLAN_MAX_MLO_GROUPS) { 352 mgmt_rx_reo_err("Invalid MGMT rx reo Group id"); 353 status = QDF_STATUS_E_INVAL; 354 goto cleanup; 355 } 356 357 mgmt_rx_params->reo_params->link_id = link_id; 358 mgmt_rx_params->reo_params->mlo_grp_id = ml_grp_id; 359 360 /* Populate frame descriptor */ 361 desc.type = MGMT_RX_REO_FRAME_DESC_HOST_CONSUMED_FRAME; 362 desc.nbuf = buf; 363 desc.rx_params = mgmt_rx_params; 364 desc.reo_params_copy = *mgmt_rx_params->reo_params; 365 desc.ingress_timestamp = qdf_get_log_timestamp(); 366 desc.ingress_list_size_rx = -1; 367 desc.ingress_list_insertion_pos = -1; 368 desc.egress_list_size_rx = -1; 369 desc.egress_list_insertion_pos = -1; 370 desc.queued_list = MGMT_RX_REO_LIST_TYPE_INVALID; 371 desc.drop = false; 372 desc.drop_reason = MGMT_RX_REO_INGRESS_DROP_REASON_INVALID; 373 374 wh = (struct ieee80211_frame *)qdf_nbuf_data(buf); 375 frame_type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; 376 frame_subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; 377 378 desc.frame_type = frame_type; 379 desc.frame_subtype = frame_subtype; 380 381 if (frame_type != IEEE80211_FC0_TYPE_MGT || 382 !is_mgmt_rx_reo_required(pdev, &desc)) { 383 desc.reo_required = false; 384 status = wlan_mgmt_rx_reo_algo_entry(pdev, &desc, &is_queued); 385 386 if (QDF_IS_STATUS_ERROR(status)) { 387 mgmt_rx_reo_warn_rl("Failed to execute REO algorithm"); 388 goto cleanup; 389 } 390 391 if (is_queued) { 392 mgmt_rx_reo_err("Frame is queued to reo list"); 393 return QDF_STATUS_E_FAILURE; 394 } 395 396 return tgt_mgmt_txrx_process_rx_frame(pdev, buf, 397 mgmt_rx_params); 398 } else { 399 desc.reo_required = true; 400 status = wlan_mgmt_rx_reo_algo_entry(pdev, &desc, &is_queued); 401 402 if (QDF_IS_STATUS_ERROR(status)) 403 mgmt_rx_reo_warn_rl("Failed to execute REO algorithm"); 404 405 /** 406 * If frame is queued, we shouldn't free up params and 407 * buf pointers. 408 */ 409 if (is_queued) 410 return status; 411 } 412 cleanup: 413 qdf_nbuf_free(buf); 414 free_mgmt_rx_event_params(mgmt_rx_params); 415 416 return status; 417 } 418 419 QDF_STATUS 420 tgt_mgmt_rx_reo_schedule_delivery(struct wlan_objmgr_psoc *psoc) 421 { 422 struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_txops; 423 424 mgmt_rx_reo_txops = wlan_psoc_get_mgmt_rx_reo_txops(psoc); 425 if (!mgmt_rx_reo_txops) { 426 mgmt_rx_reo_err("MGMT Rx REO txops is NULL"); 427 return QDF_STATUS_E_NULL_VALUE; 428 } 429 430 if (!mgmt_rx_reo_txops->schedule_delivery) { 431 mgmt_rx_reo_err("mgmt_rx_reo_schedule delivery is NULL"); 432 return QDF_STATUS_E_NULL_VALUE; 433 } 434 435 return mgmt_rx_reo_txops->schedule_delivery(psoc); 436 } 437