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 static struct wlan_lmac_if_wifi_pos_rx_ops * 158 target_if_wifi_pos_get_rx_ops(struct wlan_objmgr_psoc *psoc) 159 { 160 struct wlan_lmac_if_rx_ops *rx_ops; 161 162 rx_ops = wlan_psoc_get_lmac_if_rxops(psoc); 163 if (!rx_ops) { 164 wifi_pos_err("rx_ops is NULL"); 165 return NULL; 166 } 167 168 return &rx_ops->wifi_pos_rx_ops; 169 } 170 171 int target_if_wifi_pos_pasn_peer_create_ev_handler(ol_scn_t scn, 172 uint8_t *buf, 173 uint32_t len) 174 { 175 wmi_unified_t wmi_handle; 176 struct wlan_objmgr_psoc *psoc; 177 struct wlan_lmac_if_wifi_pos_rx_ops *rx_ops; 178 struct wifi_pos_pasn_peer_data *data = NULL; 179 QDF_STATUS status; 180 181 data = qdf_mem_malloc(sizeof(*data)); 182 if (!data) 183 return -ENOMEM; 184 185 psoc = target_if_get_psoc_from_scn_hdl(scn); 186 if (!psoc) { 187 target_if_err("psoc is null"); 188 qdf_mem_free(data); 189 return -EINVAL; 190 } 191 192 wlan_objmgr_psoc_get_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 193 194 if (!wlan_psoc_nif_fw_ext2_cap_get(psoc, 195 WLAN_VDEV_DELETE_ALL_PEER_SUPPORT)) { 196 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 197 qdf_mem_free(data); 198 target_if_debug("Firmware doesn't support Peer delete all"); 199 return -EPERM; 200 } 201 202 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 203 if (!wmi_handle) { 204 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 205 qdf_mem_free(data); 206 target_if_err("wmi_handle is null"); 207 return -EINVAL; 208 } 209 210 status = wmi_extract_pasn_peer_create_req(wmi_handle, buf, data); 211 if (QDF_IS_STATUS_ERROR(status)) { 212 wifi_pos_err("Extract PASN peer create failed"); 213 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 214 qdf_mem_free(data); 215 return -EINVAL; 216 } 217 218 rx_ops = target_if_wifi_pos_get_rx_ops(psoc); 219 if (!rx_ops || !rx_ops->wifi_pos_ranging_peer_create_cb) { 220 wifi_pos_err("%s is null", 221 !rx_ops ? "rx_ops" : "rx_ops_cb"); 222 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 223 qdf_mem_free(data); 224 return -EINVAL; 225 } 226 227 rx_ops->wifi_pos_ranging_peer_create_cb(psoc, data->peer_info, 228 data->vdev_id, 229 data->num_peers); 230 231 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 232 qdf_mem_free(data); 233 234 return 0; 235 } 236 237 int target_if_wifi_pos_pasn_peer_delete_ev_handler(ol_scn_t scn, 238 uint8_t *buf, 239 uint32_t len) 240 { 241 wmi_unified_t wmi_handle; 242 struct wlan_objmgr_psoc *psoc; 243 struct wlan_lmac_if_wifi_pos_rx_ops *rx_ops; 244 struct wifi_pos_pasn_peer_data *data = NULL; 245 QDF_STATUS status; 246 247 psoc = target_if_get_psoc_from_scn_hdl(scn); 248 if (!psoc) { 249 target_if_err("psoc is null"); 250 return QDF_STATUS_NOT_INITIALIZED; 251 } 252 253 wlan_objmgr_psoc_get_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 254 255 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 256 if (!wmi_handle) { 257 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 258 target_if_err("wmi_handle is null"); 259 return QDF_STATUS_NOT_INITIALIZED; 260 } 261 262 data = qdf_mem_malloc(sizeof(*data)); 263 if (!data) { 264 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 265 return QDF_STATUS_E_NOMEM; 266 } 267 268 status = wmi_extract_pasn_peer_delete_req(wmi_handle, buf, data); 269 if (QDF_IS_STATUS_ERROR(status)) { 270 wifi_pos_err("Extract PASN peer delete failed"); 271 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 272 qdf_mem_free(data); 273 return QDF_STATUS_E_NULL_VALUE; 274 } 275 276 rx_ops = target_if_wifi_pos_get_rx_ops(psoc); 277 if (!rx_ops || !rx_ops->wifi_pos_ranging_peer_delete_cb) { 278 wifi_pos_err("%s is null", 279 !rx_ops ? "rx_ops" : "rx_ops_cb"); 280 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 281 qdf_mem_free(data); 282 return QDF_STATUS_E_NULL_VALUE; 283 } 284 285 rx_ops->wifi_pos_ranging_peer_delete_cb(psoc, data->peer_info, 286 data->vdev_id, 287 data->num_peers); 288 289 wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID); 290 qdf_mem_free(data); 291 292 return 0; 293 } 294 #endif 295 296