1 /* 2 * Copyright (c) 2021, The Linux Foundation. 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 /** 18 * DOC: target_if_mgmt_txrx_rx_reo.c 19 * This file contains definitions of management rx re-ordering related APIs. 20 */ 21 22 #include <wlan_objmgr_psoc_obj.h> 23 #include <wlan_objmgr_pdev_obj.h> 24 #include <qdf_status.h> 25 #include <target_if.h> 26 #include <wlan_mgmt_txrx_rx_reo_public_structs.h> 27 #include <target_if_mgmt_txrx_rx_reo.h> 28 #include <wlan_lmac_if_api.h> 29 #include <init_deinit_lmac.h> 30 31 /** 32 * target_if_mgmt_rx_reo_fw_consumed_event_handler() - WMI event handler to 33 * process MGMT Rx FW consumed event handler 34 * @scn: Pointer to scn object 35 * @data_buf: Pointer to event buffer 36 * @data_len: Length of event buffer 37 * 38 * Return: 0 for success, else failure 39 */ 40 static int 41 target_if_mgmt_rx_reo_fw_consumed_event_handler( 42 ol_scn_t scn, uint8_t *data, uint32_t datalen) 43 { 44 struct wlan_objmgr_psoc *psoc; 45 struct wlan_objmgr_pdev *pdev; 46 struct wmi_unified *wmi_handle; 47 QDF_STATUS status; 48 struct mgmt_rx_reo_params params; 49 struct wlan_lmac_if_mgmt_rx_reo_rx_ops *mgmt_rx_reo_rx_ops; 50 51 psoc = target_if_get_psoc_from_scn_hdl(scn); 52 if (!psoc) { 53 mgmt_rx_reo_err("null psoc"); 54 return -EINVAL; 55 } 56 57 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 58 if (!wmi_handle) { 59 mgmt_rx_reo_err("wmi_handle is NULL"); 60 return -EINVAL; 61 } 62 63 status = wmi_extract_mgmt_rx_fw_consumed(wmi_handle, data, ¶ms); 64 if (QDF_IS_STATUS_ERROR(status)) { 65 mgmt_rx_reo_err("Failed to extract mgmt rx params"); 66 return -EINVAL; 67 } 68 69 mgmt_rx_reo_rx_ops = target_if_mgmt_rx_reo_get_rx_ops(psoc); 70 if (!mgmt_rx_reo_rx_ops) { 71 mgmt_rx_reo_err("rx_ops of MGMT Rx REO module is NULL"); 72 return -EINVAL; 73 } 74 75 if (!mgmt_rx_reo_rx_ops->fw_consumed_event_handler) { 76 mgmt_rx_reo_err("FW consumed event handler is NULL"); 77 return -EINVAL; 78 } 79 80 /* Take the pdev reference */ 81 pdev = wlan_objmgr_get_pdev_by_id(psoc, params.pdev_id, 82 WLAN_MGMT_SB_ID); 83 if (!pdev) { 84 mgmt_rx_reo_err("Couldn't get pdev for pdev_id: %d" 85 "on psoc: %pK", params.pdev_id, psoc); 86 return -EINVAL; 87 } 88 89 status = mgmt_rx_reo_rx_ops->fw_consumed_event_handler(pdev, ¶ms); 90 if (QDF_IS_STATUS_ERROR(status)) { 91 mgmt_rx_reo_err("FW consumed event handling failed"); 92 wlan_objmgr_pdev_release_ref(pdev, WLAN_MGMT_SB_ID); 93 return -EINVAL; 94 } 95 96 wlan_objmgr_pdev_release_ref(pdev, WLAN_MGMT_SB_ID); 97 return 0; 98 } 99 100 QDF_STATUS 101 target_if_mgmt_rx_reo_register_event_handlers(struct wlan_objmgr_psoc *psoc) 102 { 103 struct wmi_unified *wmi_handle; 104 QDF_STATUS status; 105 106 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 107 if (!wmi_handle) { 108 mgmt_rx_reo_err("Invalid WMI handle"); 109 return QDF_STATUS_E_INVAL; 110 } 111 112 status = wmi_unified_register_event_handler( 113 wmi_handle, 114 wmi_mgmt_rx_fw_consumed_eventid, 115 target_if_mgmt_rx_reo_fw_consumed_event_handler, 116 WMI_RX_UMAC_CTX); 117 118 if (QDF_IS_STATUS_ERROR(status)) 119 mgmt_rx_reo_err("Registering for MGMT Rx FW consumed event failed"); 120 121 return status; 122 } 123 124 QDF_STATUS 125 target_if_mgmt_rx_reo_unregister_event_handlers(struct wlan_objmgr_psoc *psoc) 126 { 127 struct wmi_unified *wmi_handle; 128 QDF_STATUS status; 129 130 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 131 if (!wmi_handle) { 132 mgmt_rx_reo_err("Invalid WMI handle"); 133 return QDF_STATUS_E_INVAL; 134 } 135 136 status = wmi_unified_unregister_event_handler( 137 wmi_handle, 138 wmi_mgmt_rx_fw_consumed_eventid); 139 140 if (QDF_IS_STATUS_ERROR(status)) 141 mgmt_rx_reo_err("Unregistering for MGMT Rx FW consumed event failed"); 142 143 return status; 144 } 145 146 /** 147 * target_if_mgmt_rx_reo_read_snapshot() - Read management rx-reorder snapshot 148 * @pdev: pdev pointer 149 * @snapshot_address: Snapshot address 150 * @id: Snapshot ID 151 * @snapshot_value: Pointer to snapshot value 152 * 153 * Read management rx-reorder snapshots from target. 154 * 155 * Return: QDF_STATUS 156 */ 157 static QDF_STATUS 158 target_if_mgmt_rx_reo_read_snapshot( 159 struct wlan_objmgr_pdev *pdev, 160 struct mgmt_rx_reo_snapshot *snapshot_address, 161 enum mgmt_rx_reo_shared_snapshot_id id, 162 struct mgmt_rx_reo_snapshot_params *snapshot_value) 163 { 164 bool snapshot_valid; 165 uint16_t mgmt_pkt_ctr; 166 uint16_t redundant_mgmt_pkt_ctr; 167 uint32_t global_timestamp; 168 uint32_t mgmt_rx_reo_snapshot_low; 169 uint32_t mgmt_rx_reo_snapshot_high; 170 uint8_t retry_count; 171 QDF_STATUS status; 172 struct wlan_lmac_if_mgmt_rx_reo_low_level_ops *low_level_ops; 173 174 if (!snapshot_address) { 175 mgmt_rx_reo_err("Mgmt Rx REO snapshot address null"); 176 return QDF_STATUS_E_INVAL; 177 } 178 179 if (!snapshot_value) { 180 mgmt_rx_reo_err("Mgmt Rx REO snapshot null"); 181 return QDF_STATUS_E_INVAL; 182 } 183 184 low_level_ops = target_if_get_mgmt_rx_reo_low_level_ops( 185 wlan_pdev_get_psoc(pdev)); 186 187 if (!low_level_ops) { 188 mgmt_rx_reo_err("Low level ops of MGMT Rx REO is null"); 189 return QDF_STATUS_E_FAILURE; 190 } 191 192 /* Make sure that function pointers are populated */ 193 qdf_assert_always(low_level_ops->implemented); 194 195 switch (id) { 196 case MGMT_RX_REO_SHARED_SNAPSHOT_MAC_HW: 197 case MGMT_RX_REO_SHARED_SNAPSHOT_FW_CONSUMED: 198 case MGMT_RX_REO_SHARED_SNAPSHOT_FW_FORWADED: 199 retry_count = 0; 200 for (; retry_count < MGMT_RX_REO_SNAPSHOT_READ_RETRY_LIMIT; 201 retry_count++) { 202 mgmt_rx_reo_snapshot_low = 203 snapshot_address->mgmt_rx_reo_snapshot_low; 204 mgmt_rx_reo_snapshot_high = 205 snapshot_address->mgmt_rx_reo_snapshot_high; 206 207 snapshot_valid = low_level_ops->snapshot_is_valid( 208 mgmt_rx_reo_snapshot_low); 209 if (!snapshot_valid) { 210 mgmt_rx_reo_debug("Invalid REO snapshot value"); 211 snapshot_value->valid = false; 212 return QDF_STATUS_SUCCESS; 213 } 214 215 global_timestamp = 216 low_level_ops->snapshot_get_global_timestamp( 217 mgmt_rx_reo_snapshot_low, 218 mgmt_rx_reo_snapshot_high); 219 mgmt_pkt_ctr = 220 low_level_ops->snapshot_get_mgmt_pkt_ctr( 221 mgmt_rx_reo_snapshot_low); 222 223 redundant_mgmt_pkt_ctr = 224 low_level_ops->snapshot_get_redundant_mgmt_pkt_ctr( 225 mgmt_rx_reo_snapshot_high); 226 227 if (low_level_ops->snapshot_is_consistent( 228 mgmt_pkt_ctr, redundant_mgmt_pkt_ctr)) 229 break; 230 231 mgmt_rx_reo_info("Inconsistent snapshot value low=0x%x high=0x%x", 232 mgmt_rx_reo_snapshot_low, 233 mgmt_rx_reo_snapshot_high); 234 } 235 236 if (retry_count == MGMT_RX_REO_SNAPSHOT_READ_RETRY_LIMIT) { 237 mgmt_rx_reo_debug("Read retry limit reached"); 238 snapshot_value->valid = false; 239 return QDF_STATUS_SUCCESS; 240 } 241 242 snapshot_value->valid = true; 243 snapshot_value->mgmt_pkt_ctr = mgmt_pkt_ctr; 244 snapshot_value->global_timestamp = global_timestamp; 245 status = QDF_STATUS_SUCCESS; 246 break; 247 248 default: 249 mgmt_rx_reo_err("Invalid snapshot id %d", id); 250 status = QDF_STATUS_E_INVAL; 251 break; 252 } 253 254 return status; 255 } 256 257 /** 258 * target_if_mgmt_rx_reo_get_snapshot_address() - Get management rx-reorder 259 * snapshot address(virtual address) in host memory 260 * @pdev: Pointer to pdev object 261 * @id: Snapshot ID 262 * @snapshot_address: Pointer to snapshot address where the address needs 263 * to be written 264 * 265 * Return: QDF_STATUS 266 */ 267 static QDF_STATUS 268 target_if_mgmt_rx_reo_get_snapshot_address( 269 struct wlan_objmgr_pdev *pdev, 270 enum mgmt_rx_reo_shared_snapshot_id id, 271 struct mgmt_rx_reo_snapshot **snapshot_address) 272 { 273 struct wlan_lmac_if_mgmt_rx_reo_low_level_ops *low_level_ops; 274 uint8_t link_id; 275 276 if (!pdev) { 277 mgmt_rx_reo_err("pdev is null"); 278 return QDF_STATUS_E_NULL_VALUE; 279 } 280 281 if (id >= MGMT_RX_REO_SHARED_SNAPSHOT_MAX) { 282 mgmt_rx_reo_err("Mgmt RX REO snapshot id invalid %d", id); 283 return QDF_STATUS_E_INVAL; 284 } 285 286 if (!snapshot_address) { 287 mgmt_rx_reo_err("Ref to mgmt RX REO snapshot address is null"); 288 return QDF_STATUS_E_NULL_VALUE; 289 } 290 291 low_level_ops = target_if_get_mgmt_rx_reo_low_level_ops( 292 wlan_pdev_get_psoc(pdev)); 293 294 if (!low_level_ops) { 295 mgmt_rx_reo_err("Low level ops of MGMT Rx REO is null"); 296 return QDF_STATUS_E_FAILURE; 297 } 298 299 qdf_assert_always(low_level_ops->implemented); 300 301 link_id = wlan_get_mlo_link_id_from_pdev(pdev); 302 *snapshot_address = low_level_ops->get_snapshot_address(link_id, id); 303 304 return QDF_STATUS_SUCCESS; 305 } 306 307 /** 308 * target_if_mgmt_rx_reo_filter_config() - Configure MGMT Rx REO filter 309 * @pdev: Pointer to pdev objmgr 310 * @filter: Pointer to MGMT Rx REO filter 311 * 312 * Return: QDF_STATUS_SUCCESS for success or error code 313 */ 314 static QDF_STATUS 315 target_if_mgmt_rx_reo_filter_config( 316 struct wlan_objmgr_pdev *pdev, 317 struct mgmt_rx_reo_filter *filter) 318 { 319 QDF_STATUS status; 320 struct wmi_unified *wmi_handle; 321 uint8_t pdev_id; 322 323 wmi_handle = lmac_get_pdev_wmi_handle(pdev); 324 if (!wmi_handle) { 325 mgmt_rx_reo_err("Invalid WMI handle"); 326 return QDF_STATUS_E_INVAL; 327 } 328 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 329 330 status = wmi_unified_mgmt_rx_reo_filter_config_cmd(wmi_handle, pdev_id, 331 filter); 332 if (QDF_IS_STATUS_ERROR(status)) 333 mgmt_rx_reo_err("Unable to send MGMT Rx REO Filter config cmd"); 334 335 return status; 336 } 337 338 QDF_STATUS 339 target_if_mgmt_rx_reo_extract_reo_params( 340 wmi_unified_t wmi_handle, void *evt_buf, 341 struct mgmt_rx_event_params *params) 342 { 343 if (!params) { 344 mgmt_rx_reo_err("MGMT Rx event parameters is NULL"); 345 return QDF_STATUS_E_INVAL; 346 } 347 348 return wmi_extract_mgmt_rx_reo_params(wmi_handle, evt_buf, 349 params->reo_params); 350 } 351 352 QDF_STATUS 353 target_if_mgmt_rx_reo_tx_ops_register( 354 struct wlan_lmac_if_mgmt_txrx_tx_ops *mgmt_txrx_tx_ops) 355 { 356 struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_tx_ops; 357 358 if (!mgmt_txrx_tx_ops) { 359 mgmt_rx_reo_err("mgmt_txrx txops NULL"); 360 return QDF_STATUS_E_FAILURE; 361 } 362 mgmt_rx_reo_tx_ops = &mgmt_txrx_tx_ops->mgmt_rx_reo_tx_ops; 363 mgmt_rx_reo_tx_ops->read_mgmt_rx_reo_snapshot = 364 target_if_mgmt_rx_reo_read_snapshot; 365 mgmt_rx_reo_tx_ops->get_mgmt_rx_reo_snapshot_address = 366 target_if_mgmt_rx_reo_get_snapshot_address; 367 mgmt_rx_reo_tx_ops->mgmt_rx_reo_filter_config = 368 target_if_mgmt_rx_reo_filter_config; 369 370 return QDF_STATUS_SUCCESS; 371 } 372 373 QDF_STATUS 374 target_if_mgmt_rx_reo_host_drop_handler(struct wlan_objmgr_pdev *pdev, 375 struct mgmt_rx_event_params *params) 376 { 377 struct wlan_lmac_if_mgmt_rx_reo_rx_ops *mgmt_rx_reo_rx_ops; 378 379 if (!pdev) { 380 mgmt_rx_reo_err("pdev is null"); 381 return QDF_STATUS_E_NULL_VALUE; 382 } 383 384 if (!params) { 385 mgmt_rx_reo_err("mgmt rx event params are null"); 386 return QDF_STATUS_E_NULL_VALUE; 387 } 388 389 mgmt_rx_reo_rx_ops = target_if_mgmt_rx_reo_get_rx_ops( 390 wlan_pdev_get_psoc(pdev)); 391 if (!mgmt_rx_reo_rx_ops) { 392 mgmt_rx_reo_err("rx_ops of MGMT Rx REO module is NULL"); 393 return QDF_STATUS_E_NULL_VALUE; 394 } 395 396 return mgmt_rx_reo_rx_ops->host_drop_handler(pdev, params->reo_params); 397 } 398