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 *
target_if_wifi_pos_get_rxops(struct wlan_objmgr_psoc * psoc)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
target_if_wifi_pos_oem_rsp_ev_handler(ol_scn_t scn,uint8_t * data_buf,uint32_t data_len)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
wifi_pos_oem_cap_ev_handler(ol_scn_t scn,uint8_t * buf,uint32_t len)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
wifi_pos_oem_meas_rpt_ev_handler(ol_scn_t scn,uint8_t * buf,uint32_t len)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
wifi_pos_oem_err_rpt_ev_handler(ol_scn_t scn,uint8_t * buf,uint32_t len)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 *
target_if_wifi_pos_get_rx_ops(struct wlan_objmgr_psoc * psoc)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
target_if_wifi_pos_pasn_peer_create_ev_handler(ol_scn_t scn,uint8_t * buf,uint32_t len)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
target_if_wifi_pos_pasn_peer_delete_ev_handler(ol_scn_t scn,uint8_t * buf,uint32_t len)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