1 /* 2 * Copyright (c) 2013-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 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /** 21 * DOC: target_if_wifi_pos_rx_ops.c 22 * This file defines the functions pertinent to wifi positioning component's 23 * target if layer. 24 */ 25 #include "wifi_pos_utils_pub.h" 26 #include "wifi_pos_api.h" 27 #include "wifi_pos_pasn_api.h" 28 29 #include "wmi_unified_api.h" 30 #include "wlan_lmac_if_def.h" 31 #include "target_if_wifi_pos.h" 32 #include "target_if_wifi_pos_rx_ops.h" 33 #include "wifi_pos_utils_i.h" 34 #include "target_if.h" 35 36 static struct wlan_lmac_if_wifi_pos_rx_ops * 37 target_if_wifi_pos_get_rxops(struct wlan_objmgr_psoc *psoc) 38 { 39 struct wlan_lmac_if_rx_ops *rx_ops; 40 41 if (!psoc) { 42 target_if_err("passed psoc is NULL"); 43 return NULL; 44 } 45 46 rx_ops = wlan_psoc_get_lmac_if_rxops(psoc); 47 if (!rx_ops) { 48 target_if_err("rx_ops is NULL"); 49 return NULL; 50 } 51 52 return &rx_ops->wifi_pos_rx_ops; 53 } 54 55 int target_if_wifi_pos_oem_rsp_ev_handler(ol_scn_t scn, 56 uint8_t *data_buf, 57 uint32_t data_len) 58 { 59 int ret; 60 uint8_t ring_idx = 0; 61 QDF_STATUS status; 62 uint32_t cookie = 0; 63 struct wmi_host_oem_indirect_data *indirect; 64 struct oem_data_rsp oem_rsp = {0}; 65 struct wifi_pos_psoc_priv_obj *priv_obj; 66 struct wlan_objmgr_psoc *psoc; 67 struct wlan_lmac_if_wifi_pos_rx_ops *wifi_pos_rx_ops; 68 struct wmi_oem_response_param oem_resp_param = {0}; 69 wmi_unified_t wmi_handle; 70 71 psoc = target_if_get_psoc_from_scn_hdl(scn); 72 if (!psoc) { 73 target_if_err("psoc is null"); 74 return QDF_STATUS_NOT_INITIALIZED; 75 } 76 77 wlan_objmgr_psoc_get_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 78 79 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 80 if (!wmi_handle) { 81 target_if_err("wmi_handle is null"); 82 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 83 return QDF_STATUS_NOT_INITIALIZED; 84 } 85 86 priv_obj = wifi_pos_get_psoc_priv_obj(wifi_pos_get_psoc()); 87 if (!priv_obj) { 88 target_if_err("priv_obj is null"); 89 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 90 return QDF_STATUS_NOT_INITIALIZED; 91 } 92 93 wifi_pos_rx_ops = target_if_wifi_pos_get_rxops(psoc); 94 if (!wifi_pos_rx_ops || !wifi_pos_rx_ops->oem_rsp_event_rx) { 95 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 96 target_if_err("lmac callbacks not registered"); 97 return QDF_STATUS_NOT_INITIALIZED; 98 } 99 100 ret = wmi_extract_oem_response_param(wmi_handle, 101 data_buf, 102 &oem_resp_param); 103 104 oem_rsp.rsp_len_1 = oem_resp_param.num_data1; 105 oem_rsp.data_1 = oem_resp_param.data_1; 106 107 if (oem_resp_param.num_data2) { 108 oem_rsp.rsp_len_2 = oem_resp_param.num_data2; 109 oem_rsp.data_2 = oem_resp_param.data_2; 110 } 111 112 indirect = &oem_resp_param.indirect_data; 113 status = target_if_wifi_pos_get_indirect_data(priv_obj, indirect, 114 &oem_rsp, &cookie); 115 if (QDF_IS_STATUS_ERROR(status)) { 116 target_if_err("get indirect data failed status: %d", status); 117 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 118 return QDF_STATUS_E_INVAL; 119 } 120 121 ret = wifi_pos_rx_ops->oem_rsp_event_rx(psoc, &oem_rsp); 122 if (indirect) 123 ring_idx = indirect->pdev_id - 1; 124 status = target_if_wifi_pos_replenish_ring(priv_obj, ring_idx, 125 oem_rsp.vaddr, cookie); 126 if (QDF_IS_STATUS_ERROR(status)) { 127 target_if_err("replenish failed status: %d", status); 128 ret = QDF_STATUS_E_FAILURE; 129 } 130 131 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 132 133 return ret; 134 } 135 136 int wifi_pos_oem_cap_ev_handler(ol_scn_t scn, uint8_t *buf, uint32_t len) 137 { 138 /* TBD */ 139 return 0; 140 } 141 142 int wifi_pos_oem_meas_rpt_ev_handler(ol_scn_t scn, uint8_t *buf, 143 uint32_t len) 144 { 145 /* TBD */ 146 return 0; 147 } 148 149 int wifi_pos_oem_err_rpt_ev_handler(ol_scn_t scn, uint8_t *buf, 150 uint32_t len) 151 { 152 /* TBD */ 153 return 0; 154 } 155 156 #if defined(WIFI_POS_CONVERGED) && defined(WLAN_FEATURE_RTT_11AZ_SUPPORT) 157 int target_if_wifi_pos_pasn_peer_create_ev_handler(ol_scn_t scn, 158 uint8_t *buf, 159 uint32_t len) 160 { 161 wmi_unified_t wmi_handle; 162 struct wlan_objmgr_psoc *psoc; 163 struct wlan_lmac_if_wifi_pos_rx_ops *rx_ops; 164 struct wifi_pos_pasn_peer_data *data = NULL; 165 QDF_STATUS status; 166 167 data = qdf_mem_malloc(sizeof(*data)); 168 if (!data) 169 return -ENOMEM; 170 171 psoc = target_if_get_psoc_from_scn_hdl(scn); 172 if (!psoc) { 173 target_if_err("psoc is null"); 174 qdf_mem_free(data); 175 return -EINVAL; 176 } 177 178 wlan_objmgr_psoc_get_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 179 180 if (!wlan_psoc_nif_fw_ext2_cap_get(psoc, 181 WLAN_VDEV_DELETE_ALL_PEER_SUPPORT)) { 182 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 183 qdf_mem_free(data); 184 target_if_debug("Firmware doesn't support Peer delete all"); 185 return -EPERM; 186 } 187 188 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 189 if (!wmi_handle) { 190 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 191 qdf_mem_free(data); 192 target_if_err("wmi_handle is null"); 193 return -EINVAL; 194 } 195 196 status = wmi_extract_pasn_peer_create_req(wmi_handle, buf, data); 197 if (QDF_IS_STATUS_ERROR(status)) { 198 wifi_pos_err("Extract PASN peer create failed"); 199 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 200 qdf_mem_free(data); 201 return -EINVAL; 202 } 203 204 rx_ops = wifi_pos_get_rx_ops(psoc); 205 if (!rx_ops || !rx_ops->wifi_pos_ranging_peer_create_cb) { 206 wifi_pos_err("%s is null", 207 !rx_ops ? "rx_ops" : "rx_ops_cb"); 208 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 209 qdf_mem_free(data); 210 return -EINVAL; 211 } 212 213 rx_ops->wifi_pos_ranging_peer_create_cb(psoc, data->peer_info, 214 data->vdev_id, 215 data->num_peers); 216 217 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 218 qdf_mem_free(data); 219 220 return 0; 221 } 222 223 int target_if_wifi_pos_pasn_peer_delete_ev_handler(ol_scn_t scn, 224 uint8_t *buf, 225 uint32_t len) 226 { 227 wmi_unified_t wmi_handle; 228 struct wlan_objmgr_psoc *psoc; 229 struct wlan_lmac_if_wifi_pos_rx_ops *rx_ops; 230 struct wifi_pos_pasn_peer_data *data = NULL; 231 QDF_STATUS status; 232 233 psoc = target_if_get_psoc_from_scn_hdl(scn); 234 if (!psoc) { 235 target_if_err("psoc is null"); 236 return QDF_STATUS_NOT_INITIALIZED; 237 } 238 239 wlan_objmgr_psoc_get_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 240 241 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 242 if (!wmi_handle) { 243 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 244 target_if_err("wmi_handle is null"); 245 return QDF_STATUS_NOT_INITIALIZED; 246 } 247 248 data = qdf_mem_malloc(sizeof(*data)); 249 if (!data) { 250 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 251 return QDF_STATUS_E_NOMEM; 252 } 253 254 status = wmi_extract_pasn_peer_delete_req(wmi_handle, buf, data); 255 if (QDF_IS_STATUS_ERROR(status)) { 256 wifi_pos_err("Extract PASN peer delete failed"); 257 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 258 qdf_mem_free(data); 259 return QDF_STATUS_E_NULL_VALUE; 260 } 261 262 rx_ops = wifi_pos_get_rx_ops(psoc); 263 if (!rx_ops || !rx_ops->wifi_pos_ranging_peer_delete_cb) { 264 wifi_pos_err("%s is null", 265 !rx_ops ? "rx_ops" : "rx_ops_cb"); 266 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 267 qdf_mem_free(data); 268 return QDF_STATUS_E_NULL_VALUE; 269 } 270 271 rx_ops->wifi_pos_ranging_peer_delete_cb(psoc, data->peer_info, 272 data->vdev_id, 273 data->num_peers); 274 275 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 276 qdf_mem_free(data); 277 278 return 0; 279 } 280 281 void target_if_wifi_pos_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops) 282 { 283 struct wlan_lmac_if_wifi_pos_rx_ops *wifi_pos_rx_ops = 284 &rx_ops->wifi_pos_rx_ops; 285 286 wifi_pos_rx_ops->wifi_pos_ranging_peer_create_cb = 287 wifi_pos_handle_ranging_peer_create; 288 wifi_pos_rx_ops->wifi_pos_ranging_peer_create_rsp_cb = 289 wifi_pos_handle_ranging_peer_create_rsp; 290 wifi_pos_rx_ops->wifi_pos_ranging_peer_delete_cb = 291 wifi_pos_handle_ranging_peer_delete; 292 wifi_pos_rx_ops->wifi_pos_vdev_delete_all_ranging_peers_rsp_cb = 293 wifi_pos_vdev_delete_all_ranging_peers_rsp; 294 } 295 #endif 296 297