1 /* 2 * Copyright (c) 2021, The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2022 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 "../../core/src/wlan_mgmt_txrx_rx_reo_i.h" 25 #include <../../core/src/wlan_mgmt_txrx_main_i.h> 26 27 QDF_STATUS 28 tgt_mgmt_rx_reo_get_num_active_hw_links(struct wlan_objmgr_psoc *psoc, 29 int8_t *num_active_hw_links) 30 { 31 struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_txops; 32 33 mgmt_rx_reo_txops = wlan_psoc_get_mgmt_rx_reo_txops(psoc); 34 if (!mgmt_rx_reo_txops) { 35 mgmt_rx_reo_err("mgmt rx reo txops is NULL"); 36 return QDF_STATUS_E_NULL_VALUE; 37 } 38 39 if (!mgmt_rx_reo_txops->get_num_active_hw_links) { 40 mgmt_rx_reo_err("get num active hw links txops is NULL"); 41 return QDF_STATUS_E_NULL_VALUE; 42 } 43 44 return mgmt_rx_reo_txops->get_num_active_hw_links(psoc, 45 num_active_hw_links); 46 } 47 48 QDF_STATUS 49 tgt_mgmt_rx_reo_get_valid_hw_link_bitmap(struct wlan_objmgr_psoc *psoc, 50 uint16_t *valid_hw_link_bitmap) 51 { 52 struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_txops; 53 54 mgmt_rx_reo_txops = wlan_psoc_get_mgmt_rx_reo_txops(psoc); 55 if (!mgmt_rx_reo_txops) { 56 mgmt_rx_reo_err("mgmt rx reo txops is NULL"); 57 return QDF_STATUS_E_NULL_VALUE; 58 } 59 60 if (!mgmt_rx_reo_txops->get_valid_hw_link_bitmap) { 61 mgmt_rx_reo_err("get valid hw link bitmap txops is NULL"); 62 return QDF_STATUS_E_NULL_VALUE; 63 } 64 65 return mgmt_rx_reo_txops->get_valid_hw_link_bitmap(psoc, 66 valid_hw_link_bitmap); 67 } 68 69 QDF_STATUS 70 tgt_mgmt_rx_reo_read_snapshot( 71 struct wlan_objmgr_pdev *pdev, 72 struct mgmt_rx_reo_snapshot_info *snapshot_info, 73 enum mgmt_rx_reo_shared_snapshot_id id, 74 struct mgmt_rx_reo_snapshot_params *value, 75 struct mgmt_rx_reo_shared_snapshot (*raw_snapshot) 76 [MGMT_RX_REO_SNAPSHOT_B2B_READ_SWAR_RETRY_LIMIT]) 77 { 78 struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_txops; 79 80 mgmt_rx_reo_txops = wlan_pdev_get_mgmt_rx_reo_txops(pdev); 81 if (!mgmt_rx_reo_txops) { 82 mgmt_rx_reo_err("mgmt rx reo txops is NULL"); 83 return QDF_STATUS_E_INVAL; 84 } 85 86 if (!mgmt_rx_reo_txops->read_mgmt_rx_reo_snapshot) { 87 mgmt_rx_reo_err("mgmt rx reo read snapshot txops is NULL"); 88 return QDF_STATUS_E_NULL_VALUE; 89 } 90 91 return mgmt_rx_reo_txops->read_mgmt_rx_reo_snapshot(pdev, snapshot_info, 92 id, value, 93 raw_snapshot); 94 } 95 96 /** 97 * tgt_mgmt_rx_reo_enter_algo_without_buffer() - Entry point to the MGMT Rx REO 98 * algorithm when there is no frame buffer 99 * @pdev: pdev for which this frame/event is intended 100 * @reo_params: MGMT Rx REO parameters corresponding to this frame/event 101 * @type: Type of the MGMT Rx REO frame/event descriptor 102 * 103 * Return: QDF_STATUS of operation 104 */ 105 static QDF_STATUS 106 tgt_mgmt_rx_reo_enter_algo_without_buffer( 107 struct wlan_objmgr_pdev *pdev, 108 struct mgmt_rx_reo_params *reo_params, 109 enum mgmt_rx_reo_frame_descriptor_type type) 110 { 111 struct mgmt_rx_event_params mgmt_rx_params = {0}; 112 struct mgmt_rx_reo_frame_descriptor desc = {0}; 113 bool is_frm_queued; 114 QDF_STATUS status; 115 int8_t link_id; 116 117 if (!pdev) { 118 mgmt_rx_reo_err("pdev is null"); 119 return QDF_STATUS_E_NULL_VALUE; 120 } 121 122 if (!wlan_mgmt_rx_reo_is_feature_enabled_at_pdev(pdev)) 123 return QDF_STATUS_SUCCESS; 124 125 if (!reo_params) { 126 mgmt_rx_reo_err("mgmt rx reo params are null"); 127 return QDF_STATUS_E_NULL_VALUE; 128 } 129 130 link_id = wlan_get_mlo_link_id_from_pdev(pdev); 131 if (link_id < 0) { 132 mgmt_rx_reo_err("Invalid link %d for the pdev", link_id); 133 return QDF_STATUS_E_INVAL; 134 } 135 136 if (!reo_params->valid) { 137 mgmt_rx_reo_err_rl("Invalid MGMT rx REO param for link %u", 138 link_id); 139 return QDF_STATUS_E_INVAL; 140 } 141 142 reo_params->link_id = link_id; 143 144 mgmt_rx_params.reo_params = reo_params; 145 146 desc.nbuf = NULL; /* No frame buffer */ 147 desc.rx_params = &mgmt_rx_params; 148 desc.type = type; 149 desc.ingress_timestamp = qdf_get_log_timestamp(); 150 desc.list_size_rx = -1; 151 desc.list_insertion_pos = -1; 152 desc.frame_type = IEEE80211_FC0_TYPE_MGT; 153 desc.frame_subtype = 0xFF; 154 desc.reo_required = is_mgmt_rx_reo_required(pdev, &desc); 155 156 /* Enter the REO algorithm */ 157 status = wlan_mgmt_rx_reo_algo_entry(pdev, &desc, &is_frm_queued); 158 159 qdf_assert_always(!is_frm_queued); 160 161 return status; 162 } 163 164 QDF_STATUS 165 tgt_mgmt_rx_reo_fw_consumed_event_handler(struct wlan_objmgr_pdev *pdev, 166 struct mgmt_rx_reo_params *params) 167 { 168 return tgt_mgmt_rx_reo_enter_algo_without_buffer( 169 pdev, params, MGMT_RX_REO_FRAME_DESC_FW_CONSUMED_FRAME); 170 } 171 172 QDF_STATUS 173 tgt_mgmt_rx_reo_host_drop_handler(struct wlan_objmgr_pdev *pdev, 174 struct mgmt_rx_reo_params *params) 175 { 176 return tgt_mgmt_rx_reo_enter_algo_without_buffer( 177 pdev, params, MGMT_RX_REO_FRAME_DESC_ERROR_FRAME); 178 } 179 180 QDF_STATUS tgt_mgmt_rx_reo_filter_config(struct wlan_objmgr_pdev *pdev, 181 struct mgmt_rx_reo_filter *filter) 182 { 183 struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_txops; 184 185 mgmt_rx_reo_txops = wlan_pdev_get_mgmt_rx_reo_txops(pdev); 186 if (!mgmt_rx_reo_txops) { 187 mgmt_rx_reo_err("MGMT Rx REO txops is NULL"); 188 return QDF_STATUS_E_NULL_VALUE; 189 } 190 191 if (!mgmt_rx_reo_txops->mgmt_rx_reo_filter_config) { 192 mgmt_rx_reo_err("mgmt_rx_reo_filter_config is NULL"); 193 return QDF_STATUS_E_NULL_VALUE; 194 } 195 196 return mgmt_rx_reo_txops->mgmt_rx_reo_filter_config(pdev, filter); 197 } 198 199 QDF_STATUS 200 tgt_mgmt_rx_reo_get_snapshot_info 201 (struct wlan_objmgr_pdev *pdev, 202 enum mgmt_rx_reo_shared_snapshot_id id, 203 struct mgmt_rx_reo_snapshot_info *snapshot_info) 204 { 205 struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_txops; 206 207 mgmt_rx_reo_txops = wlan_pdev_get_mgmt_rx_reo_txops(pdev); 208 if (!mgmt_rx_reo_txops) { 209 mgmt_rx_reo_err("mgmt rx reo txops is NULL"); 210 return QDF_STATUS_E_NULL_VALUE; 211 } 212 213 if (!mgmt_rx_reo_txops->get_mgmt_rx_reo_snapshot_info) { 214 mgmt_rx_reo_err("txops entry for get snapshot info is null"); 215 return QDF_STATUS_E_NULL_VALUE; 216 } 217 218 return mgmt_rx_reo_txops->get_mgmt_rx_reo_snapshot_info(pdev, id, 219 snapshot_info); 220 } 221 222 QDF_STATUS tgt_mgmt_rx_reo_frame_handler( 223 struct wlan_objmgr_pdev *pdev, 224 qdf_nbuf_t buf, 225 struct mgmt_rx_event_params *mgmt_rx_params) 226 { 227 QDF_STATUS status; 228 struct mgmt_rx_reo_frame_descriptor desc = {0}; 229 bool is_queued; 230 int8_t link_id; 231 uint8_t frame_type; 232 uint8_t frame_subtype; 233 struct ieee80211_frame *wh; 234 235 if (!pdev) { 236 mgmt_rx_reo_err("pdev is NULL"); 237 status = QDF_STATUS_E_NULL_VALUE; 238 goto cleanup; 239 } 240 241 if (!wlan_mgmt_rx_reo_is_simulation_in_progress() && !buf) { 242 mgmt_rx_reo_err("nbuf is NULL"); 243 status = QDF_STATUS_E_NULL_VALUE; 244 goto cleanup; 245 } 246 247 if (!mgmt_rx_params) { 248 mgmt_rx_reo_err("MGMT rx params is NULL"); 249 status = QDF_STATUS_E_NULL_VALUE; 250 goto cleanup; 251 } 252 253 if (!wlan_mgmt_rx_reo_is_feature_enabled_at_pdev(pdev)) 254 return tgt_mgmt_txrx_process_rx_frame(pdev, buf, 255 mgmt_rx_params); 256 257 if (!mgmt_rx_params->reo_params) { 258 mgmt_rx_reo_err("MGMT rx REO params is NULL"); 259 status = QDF_STATUS_E_NULL_VALUE; 260 goto cleanup; 261 } 262 263 link_id = wlan_get_mlo_link_id_from_pdev(pdev); 264 if (link_id < 0) { 265 mgmt_rx_reo_err("Invalid link %d for the pdev", link_id); 266 status = QDF_STATUS_E_INVAL; 267 goto cleanup; 268 } 269 270 if (!mgmt_rx_params->reo_params->valid) { 271 mgmt_rx_reo_err_rl("Invalid MGMT rx REO param for link %u", 272 link_id); 273 status = QDF_STATUS_E_INVAL; 274 goto cleanup; 275 } 276 277 mgmt_rx_params->reo_params->link_id = link_id; 278 279 /* Populate frame descriptor */ 280 desc.type = MGMT_RX_REO_FRAME_DESC_HOST_CONSUMED_FRAME; 281 desc.nbuf = buf; 282 desc.rx_params = mgmt_rx_params; 283 desc.ingress_timestamp = qdf_get_log_timestamp(); 284 desc.list_size_rx = -1; 285 desc.list_insertion_pos = -1; 286 287 wh = (struct ieee80211_frame *)qdf_nbuf_data(buf); 288 frame_type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; 289 frame_subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; 290 291 desc.frame_type = frame_type; 292 desc.frame_subtype = frame_subtype; 293 294 if (frame_type != IEEE80211_FC0_TYPE_MGT || 295 !is_mgmt_rx_reo_required(pdev, &desc)) { 296 desc.reo_required = false; 297 status = wlan_mgmt_rx_reo_algo_entry(pdev, &desc, &is_queued); 298 299 if (QDF_IS_STATUS_ERROR(status)) { 300 mgmt_rx_reo_err_rl("Failed to execute REO algorithm"); 301 goto cleanup; 302 } 303 304 qdf_assert_always(!is_queued); 305 306 return tgt_mgmt_txrx_process_rx_frame(pdev, buf, 307 mgmt_rx_params); 308 } else { 309 desc.reo_required = true; 310 status = wlan_mgmt_rx_reo_algo_entry(pdev, &desc, &is_queued); 311 312 if (QDF_IS_STATUS_ERROR(status)) 313 mgmt_rx_reo_err_rl("Failed to execute REO algorithm"); 314 315 /** 316 * If frame is queued, we shouldn't free up params and 317 * buf pointers. 318 */ 319 if (is_queued) 320 return status; 321 } 322 cleanup: 323 qdf_nbuf_free(buf); 324 free_mgmt_rx_event_params(mgmt_rx_params); 325 326 return status; 327 } 328