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.list_size_rx = -1; 160 desc.list_insertion_pos = -1; 161 desc.frame_type = IEEE80211_FC0_TYPE_MGT; 162 desc.frame_subtype = 0xFF; 163 desc.reo_required = is_mgmt_rx_reo_required(pdev, &desc); 164 165 /* Enter the REO algorithm */ 166 status = wlan_mgmt_rx_reo_algo_entry(pdev, &desc, &is_frm_queued); 167 168 qdf_assert_always(!is_frm_queued); 169 170 return status; 171 } 172 173 QDF_STATUS 174 tgt_mgmt_rx_reo_fw_consumed_event_handler(struct wlan_objmgr_pdev *pdev, 175 struct mgmt_rx_reo_params *params) 176 { 177 return tgt_mgmt_rx_reo_enter_algo_without_buffer( 178 pdev, params, MGMT_RX_REO_FRAME_DESC_FW_CONSUMED_FRAME); 179 } 180 181 QDF_STATUS 182 tgt_mgmt_rx_reo_host_drop_handler(struct wlan_objmgr_pdev *pdev, 183 struct mgmt_rx_reo_params *params) 184 { 185 return tgt_mgmt_rx_reo_enter_algo_without_buffer( 186 pdev, params, MGMT_RX_REO_FRAME_DESC_ERROR_FRAME); 187 } 188 189 QDF_STATUS tgt_mgmt_rx_reo_filter_config(struct wlan_objmgr_pdev *pdev, 190 struct mgmt_rx_reo_filter *filter) 191 { 192 struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_txops; 193 194 mgmt_rx_reo_txops = wlan_pdev_get_mgmt_rx_reo_txops(pdev); 195 if (!mgmt_rx_reo_txops) { 196 mgmt_rx_reo_err("MGMT Rx REO txops is NULL"); 197 return QDF_STATUS_E_NULL_VALUE; 198 } 199 200 if (!mgmt_rx_reo_txops->mgmt_rx_reo_filter_config) { 201 mgmt_rx_reo_err("mgmt_rx_reo_filter_config is NULL"); 202 return QDF_STATUS_E_NULL_VALUE; 203 } 204 205 return mgmt_rx_reo_txops->mgmt_rx_reo_filter_config(pdev, filter); 206 } 207 208 QDF_STATUS 209 tgt_mgmt_rx_reo_get_snapshot_info 210 (struct wlan_objmgr_pdev *pdev, 211 enum mgmt_rx_reo_shared_snapshot_id id, 212 struct mgmt_rx_reo_snapshot_info *snapshot_info) 213 { 214 struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_txops; 215 216 mgmt_rx_reo_txops = wlan_pdev_get_mgmt_rx_reo_txops(pdev); 217 if (!mgmt_rx_reo_txops) { 218 mgmt_rx_reo_err("mgmt rx reo txops is NULL"); 219 return QDF_STATUS_E_NULL_VALUE; 220 } 221 222 if (!mgmt_rx_reo_txops->get_mgmt_rx_reo_snapshot_info) { 223 mgmt_rx_reo_err("txops entry for get snapshot info is null"); 224 return QDF_STATUS_E_NULL_VALUE; 225 } 226 227 return mgmt_rx_reo_txops->get_mgmt_rx_reo_snapshot_info(pdev, id, 228 snapshot_info); 229 } 230 231 bool 232 wlan_mgmt_rx_reo_check_simulation_in_progress(struct wlan_objmgr_pdev *pdev) 233 { 234 uint8_t ml_grp_id; 235 struct wlan_objmgr_psoc *psoc; 236 237 psoc = wlan_pdev_get_psoc(pdev); 238 if (!psoc) 239 return false; 240 241 if (!wlan_mlo_get_psoc_capable(psoc)) 242 return false; 243 244 ml_grp_id = wlan_get_mlo_grp_id_from_pdev(pdev); 245 if (ml_grp_id > WLAN_MAX_MLO_GROUPS) { 246 mgmt_rx_reo_err("INVALID ML Group ID for the PDEV"); 247 return false; 248 } 249 250 if (!wlan_mgmt_rx_reo_is_simulation_in_progress(ml_grp_id)) 251 return false; 252 253 return true; 254 } 255 256 QDF_STATUS tgt_mgmt_rx_reo_frame_handler( 257 struct wlan_objmgr_pdev *pdev, 258 qdf_nbuf_t buf, 259 struct mgmt_rx_event_params *mgmt_rx_params) 260 { 261 QDF_STATUS status; 262 struct mgmt_rx_reo_frame_descriptor desc = {0}; 263 bool is_queued; 264 int8_t link_id; 265 uint8_t ml_grp_id; 266 uint8_t frame_type; 267 uint8_t frame_subtype; 268 struct ieee80211_frame *wh; 269 270 if (!pdev) { 271 mgmt_rx_reo_err("pdev is NULL"); 272 status = QDF_STATUS_E_NULL_VALUE; 273 goto cleanup; 274 } 275 276 if (!wlan_mgmt_rx_reo_check_simulation_in_progress(pdev) && !buf) { 277 mgmt_rx_reo_err("nbuf is NULL"); 278 status = QDF_STATUS_E_NULL_VALUE; 279 goto cleanup; 280 } 281 282 if (!mgmt_rx_params) { 283 mgmt_rx_reo_err("MGMT rx params is NULL"); 284 status = QDF_STATUS_E_NULL_VALUE; 285 goto cleanup; 286 } 287 288 if (!wlan_mgmt_rx_reo_is_feature_enabled_at_pdev(pdev)) 289 return tgt_mgmt_txrx_process_rx_frame(pdev, buf, 290 mgmt_rx_params); 291 292 if (!mgmt_rx_params->reo_params) { 293 mgmt_rx_reo_err("MGMT rx REO params is NULL"); 294 status = QDF_STATUS_E_NULL_VALUE; 295 goto cleanup; 296 } 297 298 link_id = wlan_get_mlo_link_id_from_pdev(pdev); 299 if (link_id < 0) { 300 mgmt_rx_reo_err("Invalid link %d for the pdev", link_id); 301 status = QDF_STATUS_E_INVAL; 302 goto cleanup; 303 } 304 305 if (!mgmt_rx_params->reo_params->valid) { 306 mgmt_rx_reo_err_rl("Invalid MGMT rx REO param for link %u", 307 link_id); 308 status = QDF_STATUS_E_INVAL; 309 goto cleanup; 310 } 311 312 ml_grp_id = wlan_get_mlo_grp_id_from_pdev(pdev); 313 if (ml_grp_id > WLAN_MAX_MLO_GROUPS) { 314 mgmt_rx_reo_err("Invalid MGMT rx reo Group id"); 315 status = QDF_STATUS_E_INVAL; 316 goto cleanup; 317 } 318 319 mgmt_rx_params->reo_params->link_id = link_id; 320 mgmt_rx_params->reo_params->mlo_grp_id = ml_grp_id; 321 322 /* Populate frame descriptor */ 323 desc.type = MGMT_RX_REO_FRAME_DESC_HOST_CONSUMED_FRAME; 324 desc.nbuf = buf; 325 desc.rx_params = mgmt_rx_params; 326 desc.ingress_timestamp = qdf_get_log_timestamp(); 327 desc.list_size_rx = -1; 328 desc.list_insertion_pos = -1; 329 330 wh = (struct ieee80211_frame *)qdf_nbuf_data(buf); 331 frame_type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; 332 frame_subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; 333 334 desc.frame_type = frame_type; 335 desc.frame_subtype = frame_subtype; 336 337 if (frame_type != IEEE80211_FC0_TYPE_MGT || 338 !is_mgmt_rx_reo_required(pdev, &desc)) { 339 desc.reo_required = false; 340 status = wlan_mgmt_rx_reo_algo_entry(pdev, &desc, &is_queued); 341 342 if (QDF_IS_STATUS_ERROR(status)) { 343 mgmt_rx_reo_err_rl("Failed to execute REO algorithm"); 344 goto cleanup; 345 } 346 347 qdf_assert_always(!is_queued); 348 349 return tgt_mgmt_txrx_process_rx_frame(pdev, buf, 350 mgmt_rx_params); 351 } else { 352 desc.reo_required = true; 353 status = wlan_mgmt_rx_reo_algo_entry(pdev, &desc, &is_queued); 354 355 if (QDF_IS_STATUS_ERROR(status)) 356 mgmt_rx_reo_err_rl("Failed to execute REO algorithm"); 357 358 /** 359 * If frame is queued, we shouldn't free up params and 360 * buf pointers. 361 */ 362 if (is_queued) 363 return status; 364 } 365 cleanup: 366 qdf_nbuf_free(buf); 367 free_mgmt_rx_event_params(mgmt_rx_params); 368 369 return status; 370 } 371