blob: a8bba7c91b87d3be356c2378e712e5d49f8883df [file] [log] [blame]
Naveen Rawat89284c22017-01-23 11:20:50 -08001/*
Shashikala Prabhuc8c709f2018-12-21 18:08:38 +05302 * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
Naveen Rawat89284c22017-01-23 11:20:50 -08003 *
Naveen Rawat89284c22017-01-23 11:20:50 -08004 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
7 * copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18
Naveen Rawat89284c22017-01-23 11:20:50 -080019/**
20 * DOC: wifi_pos_main.c
21 * This file defines the important functions pertinent to
22 * wifi positioning to initialize and de-initialize the component.
23 */
Naveen Rawata8423162017-03-06 15:59:31 -080024#include "target_if_wifi_pos.h"
Naveen Rawat922724f2017-03-17 19:35:46 -070025#include "wifi_pos_oem_interface_i.h"
Naveen Rawata8423162017-03-06 15:59:31 -080026#include "wifi_pos_utils_i.h"
27#include "wifi_pos_api.h"
28#include "wifi_pos_main_i.h"
29#include "wifi_pos_ucfg_i.h"
30#include "wlan_objmgr_cmn.h"
31#include "wlan_objmgr_global_obj.h"
32#include "wlan_objmgr_psoc_obj.h"
Naveen Rawat922724f2017-03-17 19:35:46 -070033#include "wlan_objmgr_pdev_obj.h"
34#include "wlan_objmgr_vdev_obj.h"
35#include "wlan_ptt_sock_svc.h"
Naveen Rawata8423162017-03-06 15:59:31 -080036
Naveen Rawata8423162017-03-06 15:59:31 -080037#include "wlan_reg_services_api.h"
38/* forward declartion */
39struct regulatory_channel;
Naveen Rawata8423162017-03-06 15:59:31 -080040
Ashish Kumar Dhanotiya04c074d2018-09-14 11:14:49 +053041#define REG_SET_CHANNEL_REG_POWER(reg_info_1, val) do { \
42 reg_info_1 &= 0xff00ffff; \
43 reg_info_1 |= ((val & 0xff) << 16); \
44} while (0)
45
46/* max tx power is in 1 dBm units */
47#define REG_SET_CHANNEL_MAX_TX_POWER(reg_info_2, val) do { \
48 reg_info_2 &= 0xffff00ff; \
49 reg_info_2 |= ((val & 0xff) << 8); \
50} while (0)
51
52/* channel info consists of 6 bits of channel mode */
53
54#define REG_SET_CHANNEL_MODE(reg_channel, val) do { \
55 (reg_channel)->info &= 0xffffffc0; \
56 (reg_channel)->info |= (val); \
57} while (0)
58
Naveen Rawat922724f2017-03-17 19:35:46 -070059/*
60 * obj mgr api to iterate over vdevs does not provide a direct array or vdevs,
61 * rather takes a callback that is called for every vdev. wifi pos needs to
62 * store device mode and vdev id of all active vdevs and provide this info to
63 * user space as part of APP registration response. due to this, vdev_idx is
64 * used to identify how many vdevs have been populated by obj manager API.
65 */
66static uint32_t vdev_idx;
67
Naveen Rawata8423162017-03-06 15:59:31 -080068/**
69 * wifi_pos_get_tlv_support: indicates if firmware supports TLV wifi pos msg
70 * @psoc: psoc object
71 *
72 * Return: status of operation
73 */
74static bool wifi_pos_get_tlv_support(struct wlan_objmgr_psoc *psoc)
75{
76 /* this is TBD */
77 return true;
78}
79
Abhiram Jogadenu1c2b5832019-07-12 11:03:04 +053080struct wlan_lmac_if_wifi_pos_tx_ops *
81 wifi_pos_get_tx_ops(struct wlan_objmgr_psoc *psoc)
82{
83 if (!psoc) {
84 wifi_pos_err("psoc is null");
85 return NULL;
86 }
87
88 return &psoc->soc_cb.tx_ops.wifi_pos_tx_ops;
89}
90
Naveen Rawatfc5e85f2017-12-20 16:18:06 -080091static QDF_STATUS wifi_pos_process_data_req(struct wlan_objmgr_psoc *psoc,
Naveen Rawat922724f2017-03-17 19:35:46 -070092 struct wifi_pos_req_msg *req)
93{
94 uint8_t idx;
95 uint32_t sub_type = 0;
96 uint32_t channel_mhz = 0;
Kiran Venkatappa2e5d58d2019-07-23 17:42:51 +053097 uint32_t pdev_id = 0;
Naveen Rawat922724f2017-03-17 19:35:46 -070098 uint32_t offset;
99 struct oem_data_req data_req;
100 struct wlan_lmac_if_wifi_pos_tx_ops *tx_ops;
Kiran Venkatappa2e5d58d2019-07-23 17:42:51 +0530101 struct wlan_objmgr_pdev *pdev;
Kiran Venkatappad2ede022019-07-31 23:03:07 +0530102 struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
103 wifi_pos_get_psoc_priv_obj(psoc);
104
105 if (!wifi_pos_obj) {
106 wifi_pos_err("wifi_pos priv obj is null");
107 return QDF_STATUS_E_INVAL;
108 }
Naveen Rawat922724f2017-03-17 19:35:46 -0700109
110 wifi_pos_debug("Received data req pid(%d), len(%d)",
111 req->pid, req->buf_len);
112
113 /* look for fields */
114 if (req->field_info_buf)
115 for (idx = 0; idx < req->field_info_buf->count; idx++) {
116 offset = req->field_info_buf->fields[idx].offset;
117 /*
118 * replace following reads with read_api based on
119 * length
120 */
121 if (req->field_info_buf->fields[idx].id ==
122 WMIRTT_FIELD_ID_oem_data_sub_type) {
123 sub_type = *((uint32_t *)&req->buf[offset]);
124 continue;
125 }
126
127 if (req->field_info_buf->fields[idx].id ==
128 WMIRTT_FIELD_ID_channel_mhz) {
129 channel_mhz = *((uint32_t *)&req->buf[offset]);
130 continue;
131 }
132
133 if (req->field_info_buf->fields[idx].id ==
134 WMIRTT_FIELD_ID_pdev) {
Kiran Venkatappa2e5d58d2019-07-23 17:42:51 +0530135 pdev_id = *((uint32_t *)&req->buf[offset]);
136 /* pdev_id in FW starts from 1. So convert it to
137 * host id by decrementing it.
138 * zero has special meaning due to backward
139 * compatibility. Dont change it.
140 */
141 if (pdev_id)
142 pdev_id -= 1;
Naveen Rawat922724f2017-03-17 19:35:46 -0700143 continue;
144 }
145 }
146
147 switch (sub_type) {
148 case TARGET_OEM_CAPABILITY_REQ:
149 /* TBD */
150 break;
151 case TARGET_OEM_CONFIGURE_LCR:
152 /* TBD */
153 break;
154 case TARGET_OEM_CONFIGURE_LCI:
155 /* TBD */
156 break;
157 case TARGET_OEM_MEASUREMENT_REQ:
158 /* TBD */
159 break;
160 case TARGET_OEM_CONFIGURE_FTMRR:
Kiran Venkatappad2ede022019-07-31 23:03:07 +0530161 wifi_pos_debug("FTMRR request");
162 if (wifi_pos_obj->wifi_pos_send_action)
163 wifi_pos_obj->wifi_pos_send_action(psoc, sub_type,
164 req->buf,
165 req->buf_len);
Naveen Rawat922724f2017-03-17 19:35:46 -0700166 break;
167 case TARGET_OEM_CONFIGURE_WRU:
Kiran Venkatappad2ede022019-07-31 23:03:07 +0530168 wifi_pos_debug("WRU request");
169 if (wifi_pos_obj->wifi_pos_send_action)
170 wifi_pos_obj->wifi_pos_send_action(psoc, sub_type,
171 req->buf,
172 req->buf_len);
Naveen Rawat922724f2017-03-17 19:35:46 -0700173 break;
174 default:
175 wifi_pos_debug("invalid sub type or not passed");
Kiran Venkatappa2e5d58d2019-07-23 17:42:51 +0530176
Abhiram Jogadenu1c2b5832019-07-12 11:03:04 +0530177 tx_ops = wifi_pos_get_tx_ops(psoc);
Naveen Rawatfc5e85f2017-12-20 16:18:06 -0800178 if (!tx_ops) {
179 wifi_pos_err("tx ops null");
180 return QDF_STATUS_E_INVAL;
181 }
Kiran Venkatappa2e5d58d2019-07-23 17:42:51 +0530182
183 pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id,
184 WLAN_WIFI_POS_CORE_ID);
185 if (pdev) {
186 data_req.data_len = req->buf_len;
187 data_req.data = req->buf;
188 tx_ops->data_req_tx(pdev, &data_req);
189 wlan_objmgr_pdev_release_ref(pdev,
190 WLAN_WIFI_POS_CORE_ID);
191 }
Naveen Rawat922724f2017-03-17 19:35:46 -0700192 break;
193 }
194
Naveen Rawatfc5e85f2017-12-20 16:18:06 -0800195 return QDF_STATUS_SUCCESS;
Naveen Rawat922724f2017-03-17 19:35:46 -0700196}
197
Naveen Rawatfc5e85f2017-12-20 16:18:06 -0800198static QDF_STATUS wifi_pos_process_set_cap_req(struct wlan_objmgr_psoc *psoc,
Naveen Rawat922724f2017-03-17 19:35:46 -0700199 struct wifi_pos_req_msg *req)
200{
201 int error_code;
202 struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
203 wifi_pos_get_psoc_priv_obj(psoc);
204 struct wifi_pos_user_defined_caps *caps =
205 (struct wifi_pos_user_defined_caps *)req->buf;
206
Qun Zhangb3606a82018-12-26 17:08:07 +0800207 if (!wifi_pos_obj) {
208 wifi_pos_err("wifi_pos priv obj is null");
209 return QDF_STATUS_E_INVAL;
210 }
211
Naveen Rawat922724f2017-03-17 19:35:46 -0700212 wifi_pos_debug("Received set cap req pid(%d), len(%d)",
213 req->pid, req->buf_len);
214
215 wifi_pos_obj->ftm_rr = caps->ftm_rr;
216 wifi_pos_obj->lci_capability = caps->lci_capability;
217 error_code = qdf_status_to_os_return(QDF_STATUS_SUCCESS);
218 wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid,
219 ANI_MSG_SET_OEM_CAP_RSP,
220 sizeof(error_code),
221 (uint8_t *)&error_code);
222
Naveen Rawatfc5e85f2017-12-20 16:18:06 -0800223 return QDF_STATUS_SUCCESS;
Naveen Rawat922724f2017-03-17 19:35:46 -0700224}
225
Naveen Rawatfc5e85f2017-12-20 16:18:06 -0800226static QDF_STATUS wifi_pos_process_get_cap_req(struct wlan_objmgr_psoc *psoc,
Naveen Rawat922724f2017-03-17 19:35:46 -0700227 struct wifi_pos_req_msg *req)
228{
229 struct wifi_pos_oem_get_cap_rsp cap_rsp = { { {0} } };
230 struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
231 wifi_pos_get_psoc_priv_obj(psoc);
232
Qun Zhangb3606a82018-12-26 17:08:07 +0800233 if (!wifi_pos_obj) {
234 wifi_pos_err("wifi_pos priv obj is null");
235 return QDF_STATUS_E_INVAL;
236 }
237
Naveen Rawat922724f2017-03-17 19:35:46 -0700238 wifi_pos_debug("Received get cap req pid(%d), len(%d)",
239 req->pid, req->buf_len);
240
241 wifi_pos_populate_caps(psoc, &cap_rsp.driver_cap);
242 cap_rsp.user_defined_cap.ftm_rr = wifi_pos_obj->ftm_rr;
243 cap_rsp.user_defined_cap.lci_capability = wifi_pos_obj->lci_capability;
244 wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid,
245 ANI_MSG_GET_OEM_CAP_RSP,
246 sizeof(cap_rsp),
247 (uint8_t *)&cap_rsp);
248
Naveen Rawatfc5e85f2017-12-20 16:18:06 -0800249 return QDF_STATUS_SUCCESS;
Naveen Rawat922724f2017-03-17 19:35:46 -0700250}
251
Kiran Venkatappad2ede022019-07-31 23:03:07 +0530252QDF_STATUS wifi_pos_send_report_resp(struct wlan_objmgr_psoc *psoc,
253 int req_id, uint8_t *dest_mac,
254 int err_code)
255{
256 struct wifi_pos_err_msg_report err_report = {0};
257 struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
258 wifi_pos_get_psoc_priv_obj(psoc);
259
260 if (!wifi_pos_obj) {
261 wifi_pos_err("wifi_pos priv obj is null");
262 return QDF_STATUS_E_INVAL;
263 }
264
265 err_report.msg_tag_len = OEM_MSG_RSP_HEAD_TAG_ID << 16;
266 err_report.msg_tag_len |= (sizeof(err_report) -
267 sizeof(err_report.err_rpt)) & 0x0000FFFF;
268 err_report.msg_subtype = TARGET_OEM_ERROR_REPORT_RSP;
269 err_report.req_id = req_id & 0xFFFF;
270 err_report.req_id |= ((err_code & 0xFF) << 16);
271 err_report.req_id |= (0x1 << 24);
272 err_report.time_left = 0xFFFFFFFF;
273 err_report.err_rpt.tag_len = OEM_MEAS_RSP_HEAD_TAG_ID << 16;
274 err_report.err_rpt.tag_len |=
275 (sizeof(struct wifi_pos_err_rpt)) & 0x0000FFFF;
276 memcpy(&err_report.err_rpt.dest_mac, dest_mac, QDF_MAC_ADDR_SIZE);
277
278 wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid,
279 ANI_MSG_OEM_DATA_RSP,
280 sizeof(err_report),
281 (uint8_t *)&err_report);
282
283 return QDF_STATUS_SUCCESS;
284}
285
Ashish Kumar Dhanotiya04c074d2018-09-14 11:14:49 +0530286static void wifi_update_channel_bw_info(struct wlan_objmgr_psoc *psoc,
287 struct wlan_objmgr_pdev *pdev,
288 uint16_t chan,
289 struct wifi_pos_ch_info_rsp *chan_info)
290{
291 struct ch_params ch_params = {0};
292 uint16_t sec_ch_2g = 0;
293 struct wifi_pos_psoc_priv_obj *wifi_pos_psoc =
294 wifi_pos_get_psoc_priv_obj(psoc);
295 uint32_t phy_mode;
296
297 if (!wifi_pos_psoc) {
298 wifi_pos_err("wifi_pos priv obj is null");
299 return;
300 }
301
302 /* Passing CH_WIDTH_MAX will give the max bandwidth supported */
303 ch_params.ch_width = CH_WIDTH_MAX;
304
305 wlan_reg_set_channel_params(pdev, chan, sec_ch_2g, &ch_params);
306 if (ch_params.center_freq_seg0)
307 chan_info->band_center_freq1 =
Ashish Kumar Dhanotiya4260dcf2019-10-16 18:50:45 +0530308 wlan_reg_legacy_chan_to_freq(
309 pdev,
310 ch_params.center_freq_seg0);
Ashish Kumar Dhanotiya04c074d2018-09-14 11:14:49 +0530311
312 wifi_pos_psoc->wifi_pos_get_phy_mode(chan, ch_params.ch_width,
313 &phy_mode);
314
315 REG_SET_CHANNEL_MODE(chan_info, phy_mode);
316}
317
318static void wifi_pos_get_reg_info(struct wlan_objmgr_pdev *pdev,
319 uint32_t chan_num, uint32_t *reg_info_1,
320 uint32_t *reg_info_2)
321{
322 uint32_t reg_power = wlan_reg_get_channel_reg_power(pdev, chan_num);
323
324 *reg_info_1 = 0;
325 *reg_info_2 = 0;
326
327 REG_SET_CHANNEL_REG_POWER(*reg_info_1, reg_power);
328 REG_SET_CHANNEL_MAX_TX_POWER(*reg_info_2, reg_power);
329}
330
331/**
332 * wifi_pos_get_valid_channels: Get the list of valid channels from the
333 * given channel list
334 * @channels: Channel list to be validated
335 * @num_ch: NUmber of channels in the channel list to be validated
336 * @valid_channel_list: Pointer to valid channel list
337 *
338 * Return: Number of valid channels in the given list
339 */
340
341static uint32_t wifi_pos_get_valid_channels(uint8_t *channels, uint32_t num_ch,
342 uint8_t *valid_channel_list) {
343 uint32_t i, num_valid_channels = 0;
344
345 for (i = 0; i < num_ch; i++) {
Shashikala Prabhuc8c709f2018-12-21 18:08:38 +0530346 if (wlan_reg_get_chan_enum(channels[i]) == INVALID_CHANNEL)
Ashish Kumar Dhanotiya04c074d2018-09-14 11:14:49 +0530347 continue;
348 valid_channel_list[num_valid_channels++] = channels[i];
349 }
350 return num_valid_channels;
351}
352
Naveen Rawatfc5e85f2017-12-20 16:18:06 -0800353static QDF_STATUS wifi_pos_process_ch_info_req(struct wlan_objmgr_psoc *psoc,
Naveen Rawat922724f2017-03-17 19:35:46 -0700354 struct wifi_pos_req_msg *req)
355{
356 uint8_t idx;
357 uint8_t *buf;
358 uint32_t len;
Ashish Kumar Dhanotiya04c074d2018-09-14 11:14:49 +0530359 uint32_t reg_info_1;
360 uint32_t reg_info_2;
Naveen Rawat922724f2017-03-17 19:35:46 -0700361 uint8_t *channels = req->buf;
Naveen Rawat0b448282017-11-10 10:51:20 -0800362 struct wlan_objmgr_pdev *pdev;
Naveen Rawat922724f2017-03-17 19:35:46 -0700363 uint32_t num_ch = req->buf_len;
Ashish Kumar Dhanotiya04c074d2018-09-14 11:14:49 +0530364 uint8_t valid_channel_list[NUM_CHANNELS];
365 uint32_t num_valid_channels;
Naveen Rawat922724f2017-03-17 19:35:46 -0700366 struct wifi_pos_ch_info_rsp *ch_info;
367 struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
368 wifi_pos_get_psoc_priv_obj(psoc);
369
Qun Zhangb3606a82018-12-26 17:08:07 +0800370 if (!wifi_pos_obj) {
371 wifi_pos_err("wifi_pos priv obj is null");
372 return QDF_STATUS_E_INVAL;
373 }
374
Naveen Rawat922724f2017-03-17 19:35:46 -0700375 wifi_pos_debug("Received ch info req pid(%d), len(%d)",
376 req->pid, req->buf_len);
377
Naveen Rawat0b448282017-11-10 10:51:20 -0800378 /* get first pdev since we need that only for freq and dfs state */
Naveen Rawat2d397102018-05-04 17:05:20 -0700379 pdev = wlan_objmgr_get_pdev_by_id(psoc, 0, WLAN_WIFI_POS_CORE_ID);
Naveen Rawat0b448282017-11-10 10:51:20 -0800380 if (!pdev) {
381 wifi_pos_err("pdev get API failed");
Naveen Rawatfc5e85f2017-12-20 16:18:06 -0800382 return QDF_STATUS_E_INVAL;
Naveen Rawat0b448282017-11-10 10:51:20 -0800383 }
Ashish Kumar Dhanotiya04c074d2018-09-14 11:14:49 +0530384 if (num_ch > NUM_CHANNELS) {
385 wifi_pos_err("Invalid number of channels");
386 return QDF_STATUS_E_INVAL;
387 }
388 num_valid_channels = wifi_pos_get_valid_channels(channels, num_ch,
389 valid_channel_list);
Naveen Rawat0b448282017-11-10 10:51:20 -0800390
Ashish Kumar Dhanotiya04c074d2018-09-14 11:14:49 +0530391 len = sizeof(uint8_t) + sizeof(struct wifi_pos_ch_info_rsp) *
392 num_valid_channels;
Naveen Rawat922724f2017-03-17 19:35:46 -0700393 buf = qdf_mem_malloc(len);
394 if (!buf) {
Naveen Rawat2d397102018-05-04 17:05:20 -0700395 wlan_objmgr_pdev_release_ref(pdev, WLAN_WIFI_POS_CORE_ID);
Naveen Rawatfc5e85f2017-12-20 16:18:06 -0800396 return QDF_STATUS_E_NOMEM;
Naveen Rawat922724f2017-03-17 19:35:46 -0700397 }
398
Ashish Kumar Dhanotiya04c074d2018-09-14 11:14:49 +0530399 qdf_mem_zero(buf, len);
400
Naveen Rawat922724f2017-03-17 19:35:46 -0700401 /* First byte of message body will have num of channels */
Ashish Kumar Dhanotiya04c074d2018-09-14 11:14:49 +0530402 buf[0] = num_valid_channels;
Naveen Rawat922724f2017-03-17 19:35:46 -0700403 ch_info = (struct wifi_pos_ch_info_rsp *)&buf[1];
Ashish Kumar Dhanotiya04c074d2018-09-14 11:14:49 +0530404 for (idx = 0; idx < num_valid_channels; idx++) {
405 ch_info[idx].chan_id = valid_channel_list[idx];
406 wifi_pos_get_reg_info(pdev, ch_info[idx].chan_id,
407 &reg_info_1, &reg_info_2);
Naveen Rawat922724f2017-03-17 19:35:46 -0700408 ch_info[idx].reserved0 = 0;
Ashish Kumar Dhanotiya04c074d2018-09-14 11:14:49 +0530409 ch_info[idx].mhz = wlan_reg_get_channel_freq(
410 pdev,
411 valid_channel_list[idx]);
Naveen Rawat922724f2017-03-17 19:35:46 -0700412 ch_info[idx].band_center_freq1 = ch_info[idx].mhz;
Naveen Rawat922724f2017-03-17 19:35:46 -0700413 ch_info[idx].band_center_freq2 = 0;
414 ch_info[idx].info = 0;
Ashish Kumar Dhanotiya04c074d2018-09-14 11:14:49 +0530415 if (wlan_reg_is_dfs_ch(pdev, valid_channel_list[idx]))
Naveen Rawat0b448282017-11-10 10:51:20 -0800416 WIFI_POS_SET_DFS(ch_info[idx].info);
Ashish Kumar Dhanotiya04c074d2018-09-14 11:14:49 +0530417
418 wifi_update_channel_bw_info(psoc, pdev,
419 ch_info[idx].chan_id,
420 &ch_info[idx]);
421
422 ch_info[idx].reg_info_1 = reg_info_1;
423 ch_info[idx].reg_info_2 = reg_info_2;
Naveen Rawat922724f2017-03-17 19:35:46 -0700424 }
425
426 wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid,
427 ANI_MSG_CHANNEL_INFO_RSP,
428 len, buf);
429 qdf_mem_free(buf);
Naveen Rawat2d397102018-05-04 17:05:20 -0700430 wlan_objmgr_pdev_release_ref(pdev, WLAN_WIFI_POS_CORE_ID);
Naveen Rawatfc5e85f2017-12-20 16:18:06 -0800431
432 return QDF_STATUS_SUCCESS;
Naveen Rawat922724f2017-03-17 19:35:46 -0700433}
434
Naveen Rawat0b448282017-11-10 10:51:20 -0800435static void wifi_pos_vdev_iterator(struct wlan_objmgr_psoc *psoc,
436 void *vdev, void *arg)
Naveen Rawat922724f2017-03-17 19:35:46 -0700437{
438 struct app_reg_rsp_vdev_info *vdev_info = arg;
439
Naveen Rawat922724f2017-03-17 19:35:46 -0700440 vdev_info[vdev_idx].dev_mode = wlan_vdev_mlme_get_opmode(vdev);
441 vdev_info[vdev_idx].vdev_id = wlan_vdev_get_id(vdev);
Naveen Rawat922724f2017-03-17 19:35:46 -0700442 vdev_idx++;
443}
444
Naveen Rawatfc5e85f2017-12-20 16:18:06 -0800445static QDF_STATUS wifi_pos_process_app_reg_req(struct wlan_objmgr_psoc *psoc,
Naveen Rawat922724f2017-03-17 19:35:46 -0700446 struct wifi_pos_req_msg *req)
447{
Naveen Rawatfc5e85f2017-12-20 16:18:06 -0800448 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Naveen Rawat922724f2017-03-17 19:35:46 -0700449 uint8_t err = 0;
450 uint32_t rsp_len;
451 char *sign_str = NULL;
452 struct wifi_app_reg_rsp *app_reg_rsp;
453 struct app_reg_rsp_vdev_info vdevs_info[WLAN_UMAC_PSOC_MAX_VDEVS]
454 = { { 0 } };
455 struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
456 wifi_pos_get_psoc_priv_obj(psoc);
457
Qun Zhangb3606a82018-12-26 17:08:07 +0800458 if (!wifi_pos_obj) {
459 wifi_pos_err("wifi_pos priv obj is null");
460 return QDF_STATUS_E_INVAL;
461 }
462
Naveen Rawat922724f2017-03-17 19:35:46 -0700463 wifi_pos_err("Received App Req Req pid(%d), len(%d)",
464 req->pid, req->buf_len);
465
466 sign_str = (char *)req->buf;
Kapil Gupta09b574f2017-07-18 17:14:35 +0530467 /* Registration request is only allowed for QTI Application */
Naveen Rawat922724f2017-03-17 19:35:46 -0700468 if ((OEM_APP_SIGNATURE_LEN != req->buf_len) ||
469 (strncmp(sign_str, OEM_APP_SIGNATURE_STR,
470 OEM_APP_SIGNATURE_LEN))) {
471 wifi_pos_err("Invalid signature pid(%d)", req->pid);
Naveen Rawatfc5e85f2017-12-20 16:18:06 -0800472 ret = QDF_STATUS_E_PERM;
Naveen Rawat922724f2017-03-17 19:35:46 -0700473 err = OEM_ERR_INVALID_SIGNATURE;
474 goto app_reg_failed;
475 }
476
477 wifi_pos_debug("Valid App Req Req from pid(%d)", req->pid);
Paul Zhangd2dad4b2018-12-28 11:17:40 +0800478 qdf_spin_lock_bh(&wifi_pos_obj->wifi_pos_lock);
Naveen Rawat922724f2017-03-17 19:35:46 -0700479 wifi_pos_obj->is_app_registered = true;
480 wifi_pos_obj->app_pid = req->pid;
Paul Zhangd2dad4b2018-12-28 11:17:40 +0800481 qdf_spin_unlock_bh(&wifi_pos_obj->wifi_pos_lock);
Naveen Rawat922724f2017-03-17 19:35:46 -0700482
483 vdev_idx = 0;
484 wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
Naveen Rawat0b448282017-11-10 10:51:20 -0800485 wifi_pos_vdev_iterator,
Naveen Rawat2d397102018-05-04 17:05:20 -0700486 vdevs_info, true, WLAN_WIFI_POS_CORE_ID);
Naveen Rawat922724f2017-03-17 19:35:46 -0700487 rsp_len = (sizeof(struct app_reg_rsp_vdev_info) * vdev_idx)
488 + sizeof(uint8_t);
489 app_reg_rsp = qdf_mem_malloc(rsp_len);
490 if (!app_reg_rsp) {
Naveen Rawatfc5e85f2017-12-20 16:18:06 -0800491 ret = QDF_STATUS_E_NOMEM;
Naveen Rawat922724f2017-03-17 19:35:46 -0700492 err = OEM_ERR_NULL_CONTEXT;
493 goto app_reg_failed;
494 }
495
496 app_reg_rsp->num_inf = vdev_idx;
497 qdf_mem_copy(&app_reg_rsp->vdevs, vdevs_info,
498 sizeof(struct app_reg_rsp_vdev_info) * vdev_idx);
499 if (!vdev_idx)
500 wifi_pos_debug("no active vdev");
501
502 vdev_idx = 0;
503 wifi_pos_obj->wifi_pos_send_rsp(req->pid, ANI_MSG_APP_REG_RSP,
504 rsp_len, (uint8_t *)app_reg_rsp);
505
506 qdf_mem_free(app_reg_rsp);
507 return ret;
508
509app_reg_failed:
510
511 wifi_pos_obj->wifi_pos_send_rsp(req->pid, ANI_MSG_OEM_ERROR,
512 sizeof(err), &err);
513 return ret;
514}
515
Naveen Rawata8423162017-03-06 15:59:31 -0800516/**
517 * wifi_pos_tlv_callback: wifi pos msg handler registered for TLV type req
518 * @wmi_msg: wmi type request msg
519 *
520 * Return: status of operation
521 */
522static QDF_STATUS wifi_pos_tlv_callback(struct wlan_objmgr_psoc *psoc,
523 struct wifi_pos_req_msg *req)
524{
Naveen Rawat922724f2017-03-17 19:35:46 -0700525 wifi_pos_debug("enter: msg_type: %d", req->msg_type);
526 switch (req->msg_type) {
527 case ANI_MSG_APP_REG_REQ:
528 return wifi_pos_process_app_reg_req(psoc, req);
529 case ANI_MSG_OEM_DATA_REQ:
530 return wifi_pos_process_data_req(psoc, req);
531 case ANI_MSG_CHANNEL_INFO_REQ:
532 return wifi_pos_process_ch_info_req(psoc, req);
533 case ANI_MSG_SET_OEM_CAP_REQ:
534 return wifi_pos_process_set_cap_req(psoc, req);
535 case ANI_MSG_GET_OEM_CAP_REQ:
536 return wifi_pos_process_get_cap_req(psoc, req);
537 default:
538 wifi_pos_err("invalid request type");
539 break;
540 }
541 return 0;
Naveen Rawata8423162017-03-06 15:59:31 -0800542}
543
544/**
545 * wifi_pos_non_tlv_callback: wifi pos msg handler registered for non-TLV
546 * type req
547 * @wmi_msg: wmi type request msg
548 *
549 * Return: status of operation
550 */
551static QDF_STATUS wifi_pos_non_tlv_callback(struct wlan_objmgr_psoc *psoc,
552 struct wifi_pos_req_msg *req)
553{
554 return QDF_STATUS_SUCCESS;
555}
556
557QDF_STATUS wifi_pos_psoc_obj_created_notification(
558 struct wlan_objmgr_psoc *psoc, void *arg_list)
559{
560 QDF_STATUS status;
561 struct wifi_pos_psoc_priv_obj *wifi_pos_obj;
562
563 /*
564 * this is for WIN, if they have multiple psoc, we dont want to create
565 * multiple priv object. Since there is just one LOWI app registered to
566 * one driver, avoid 2nd private object with another psoc.
567 */
568 if (wifi_pos_get_psoc()) {
569 wifi_pos_debug("global psoc obj already set. do not allocate another psoc private object");
570 return QDF_STATUS_SUCCESS;
571 } else {
572 wifi_pos_debug("setting global pos object");
573 wifi_pos_set_psoc(psoc);
574 }
575
576 /* initialize wifi-pos psoc priv object */
577 wifi_pos_obj = qdf_mem_malloc(sizeof(*wifi_pos_obj));
578 if (!wifi_pos_obj) {
Naveen Rawata8423162017-03-06 15:59:31 -0800579 wifi_pos_clear_psoc();
580 return QDF_STATUS_E_NOMEM;
581 }
582
583 qdf_spinlock_create(&wifi_pos_obj->wifi_pos_lock);
584 /* Register TLV or non-TLV callbacks depending on target fw version */
585 if (wifi_pos_get_tlv_support(psoc))
586 wifi_pos_obj->wifi_pos_req_handler = wifi_pos_tlv_callback;
587 else
588 wifi_pos_obj->wifi_pos_req_handler = wifi_pos_non_tlv_callback;
589
590 /*
591 * MGMT Rx is not handled in this phase since wifi pos only uses few
592 * measurement subtypes under RRM_RADIO_MEASURE_REQ. Rest of them are
593 * used for 80211k. That part is not yet converged and still follows
594 * legacy MGMT Rx to work. Action frame in new TXRX can be registered
595 * at per ACTION Frame type granularity only.
596 */
597
598 status = wlan_objmgr_psoc_component_obj_attach(psoc,
599 WLAN_UMAC_COMP_WIFI_POS,
600 wifi_pos_obj,
601 QDF_STATUS_SUCCESS);
602
603 if (QDF_IS_STATUS_ERROR(status)) {
604 wifi_pos_err("obj attach with psoc failed with status: %d",
605 status);
606 qdf_spinlock_destroy(&wifi_pos_obj->wifi_pos_lock);
607 qdf_mem_free(wifi_pos_obj);
608 wifi_pos_clear_psoc();
609 }
610
611 return status;
612}
613
614QDF_STATUS wifi_pos_psoc_obj_destroyed_notification(
615 struct wlan_objmgr_psoc *psoc, void *arg_list)
616{
617 QDF_STATUS status;
618 struct wifi_pos_psoc_priv_obj *wifi_pos_obj = NULL;
619
620 if (wifi_pos_get_psoc() == psoc) {
621 wifi_pos_debug("deregistering wifi_pos_psoc object");
622 wifi_pos_clear_psoc();
623 } else {
624 wifi_pos_warn("un-related PSOC closed. do nothing");
625 return QDF_STATUS_SUCCESS;
626 }
627
628 wifi_pos_obj = wifi_pos_get_psoc_priv_obj(psoc);
629 if (!wifi_pos_obj) {
630 wifi_pos_err("wifi_pos_obj is NULL");
631 return QDF_STATUS_E_FAULT;
632 }
633
Naveen Rawatba24c482017-05-15 12:02:48 -0700634 target_if_wifi_pos_deinit_dma_rings(psoc);
635
Naveen Rawata8423162017-03-06 15:59:31 -0800636 status = wlan_objmgr_psoc_component_obj_detach(psoc,
637 WLAN_UMAC_COMP_WIFI_POS,
638 wifi_pos_obj);
639 if (status != QDF_STATUS_SUCCESS)
640 wifi_pos_err("wifi_pos_obj detach failed");
641
642 wifi_pos_debug("wifi_pos_obj deleted with status %d", status);
643 qdf_spinlock_destroy(&wifi_pos_obj->wifi_pos_lock);
644 qdf_mem_free(wifi_pos_obj);
645
646 return status;
647}
648
Naveen Rawat18ceca12017-03-06 16:04:45 -0800649int wifi_pos_oem_rsp_handler(struct wlan_objmgr_psoc *psoc,
650 struct oem_data_rsp *oem_rsp)
651{
Naveen Rawat7c3c7462017-05-02 18:49:20 -0700652 uint32_t len;
653 uint8_t *data;
654 uint32_t app_pid;
655 struct wifi_pos_psoc_priv_obj *priv =
Naveen Rawat18ceca12017-03-06 16:04:45 -0800656 wifi_pos_get_psoc_priv_obj(psoc);
Naveen Rawat7c3c7462017-05-02 18:49:20 -0700657 void (*wifi_pos_send_rsp)(uint32_t, uint32_t, uint32_t, uint8_t *);
658
659 if (!priv) {
660 wifi_pos_err("private object is NULL");
661 return -EINVAL;
662 }
663
664 qdf_spin_lock_bh(&priv->wifi_pos_lock);
665 app_pid = priv->app_pid;
666 wifi_pos_send_rsp = priv->wifi_pos_send_rsp;
667 qdf_spin_unlock_bh(&priv->wifi_pos_lock);
668
669 len = oem_rsp->rsp_len_1 + oem_rsp->rsp_len_2 + oem_rsp->dma_len;
670 if (oem_rsp->rsp_len_1 > OEM_DATA_RSP_SIZE ||
671 oem_rsp->rsp_len_2 > OEM_DATA_RSP_SIZE) {
Naveen Rawat18ceca12017-03-06 16:04:45 -0800672 wifi_pos_err("invalid length of Oem Data response");
673 return -EINVAL;
674 }
675
Arif Hussain738581a2018-10-08 13:58:46 -0700676 if (!wifi_pos_send_rsp) {
677 wifi_pos_err("invalid response handler");
678 return -EINVAL;
679 }
680
Naveen Rawat7c3c7462017-05-02 18:49:20 -0700681 wifi_pos_debug("oem data rsp, len: %d to pid: %d", len, app_pid);
682
683 if (oem_rsp->rsp_len_2 + oem_rsp->dma_len) {
684 /* stitch togther the msg data_1 + CIR/CFR + data_2 */
685 data = qdf_mem_malloc(len);
Madhvapathi Sriramb73fc282019-01-07 09:12:25 +0530686 if (!data)
Naveen Rawat7c3c7462017-05-02 18:49:20 -0700687 return -ENOMEM;
Madhvapathi Sriramb73fc282019-01-07 09:12:25 +0530688
Naveen Rawat7c3c7462017-05-02 18:49:20 -0700689 qdf_mem_copy(data, oem_rsp->data_1, oem_rsp->rsp_len_1);
690 qdf_mem_copy(&data[oem_rsp->rsp_len_1],
691 oem_rsp->vaddr, oem_rsp->dma_len);
692 qdf_mem_copy(&data[oem_rsp->rsp_len_1 + oem_rsp->dma_len],
693 oem_rsp->data_2, oem_rsp->rsp_len_2);
694
695 wifi_pos_send_rsp(app_pid, ANI_MSG_OEM_DATA_RSP, len, data);
696 qdf_mem_free(data);
697 } else {
698 wifi_pos_send_rsp(app_pid, ANI_MSG_OEM_DATA_RSP,
699 oem_rsp->rsp_len_1, oem_rsp->data_1);
700 }
701
Naveen Rawat18ceca12017-03-06 16:04:45 -0800702 return 0;
703}
704
Abhiram Jogadenu1c2b5832019-07-12 11:03:04 +0530705void wifi_pos_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
706{
707 struct wlan_lmac_if_wifi_pos_rx_ops *wifi_pos_rx_ops;
708
709 wifi_pos_rx_ops = &rx_ops->wifi_pos_rx_ops;
710 wifi_pos_rx_ops->oem_rsp_event_rx = wifi_pos_oem_rsp_handler;
711}
712
Naveen Rawat0b448282017-11-10 10:51:20 -0800713static void wifi_pos_pdev_iterator(struct wlan_objmgr_psoc *psoc,
714 void *obj, void *arg)
Naveen Rawata8423162017-03-06 15:59:31 -0800715{
716 QDF_STATUS status;
Hariharan Basuthkar43168e82019-08-07 17:55:30 +0530717 uint8_t i, num_channels, size;
Naveen Rawat0b448282017-11-10 10:51:20 -0800718 struct wlan_objmgr_pdev *pdev = obj;
Ashish Kumar Dhanotiya034a01b2019-06-11 21:00:30 +0530719 struct wifi_pos_driver_caps *caps = arg;
Hariharan Basuthkar43168e82019-08-07 17:55:30 +0530720 struct channel_power *ch_list;
721
722 size = QDF_MAX(OEM_CAP_MAX_NUM_CHANNELS, NUM_CHANNELS);
723 ch_list = qdf_mem_malloc(size * sizeof(*ch_list));
724 if (!ch_list)
725 return;
Naveen Rawata8423162017-03-06 15:59:31 -0800726
Ashish Kumar Dhanotiya034a01b2019-06-11 21:00:30 +0530727 status = wlan_reg_get_channel_list_with_power(pdev, ch_list,
728 &num_channels);
729
Naveen Rawata8423162017-03-06 15:59:31 -0800730 if (QDF_IS_STATUS_ERROR(status)) {
Ashish Kumar Dhanotiya034a01b2019-06-11 21:00:30 +0530731 wifi_pos_err("Failed to get valid channel list");
Hariharan Basuthkar43168e82019-08-07 17:55:30 +0530732 qdf_mem_free(ch_list);
Naveen Rawata8423162017-03-06 15:59:31 -0800733 return;
734 }
Hariharan Basuthkar43168e82019-08-07 17:55:30 +0530735 if (num_channels > OEM_CAP_MAX_NUM_CHANNELS)
736 num_channels = OEM_CAP_MAX_NUM_CHANNELS;
737
Ashish Kumar Dhanotiya034a01b2019-06-11 21:00:30 +0530738 for (i = 0; i < num_channels; i++)
739 caps->channel_list[i] = ch_list[i].chan_num;
740 caps->num_channels = num_channels;
Hariharan Basuthkar43168e82019-08-07 17:55:30 +0530741 qdf_mem_free(ch_list);
Naveen Rawat0b448282017-11-10 10:51:20 -0800742}
743
744static void wifi_pos_get_ch_info(struct wlan_objmgr_psoc *psoc,
745 struct wifi_pos_driver_caps *caps)
746{
Naveen Rawat0b448282017-11-10 10:51:20 -0800747 wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
748 wifi_pos_pdev_iterator,
Ashish Kumar Dhanotiya034a01b2019-06-11 21:00:30 +0530749 caps, true, WLAN_WIFI_POS_CORE_ID);
750 wifi_pos_err("num channels: %d", caps->num_channels);
Naveen Rawata8423162017-03-06 15:59:31 -0800751}
Naveen Rawata8423162017-03-06 15:59:31 -0800752
753QDF_STATUS wifi_pos_populate_caps(struct wlan_objmgr_psoc *psoc,
754 struct wifi_pos_driver_caps *caps)
755{
756 struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
757 wifi_pos_get_psoc_priv_obj(psoc);
758
759 wifi_pos_debug("Enter");
760 if (!wifi_pos_obj) {
761 wifi_pos_err("wifi_pos_obj is null");
762 return QDF_STATUS_E_NULL_VALUE;
763 }
764
765 strlcpy(caps->oem_target_signature,
766 OEM_TARGET_SIGNATURE,
767 OEM_TARGET_SIGNATURE_LEN);
768 caps->oem_target_type = wifi_pos_obj->oem_target_type;
769 caps->oem_fw_version = wifi_pos_obj->oem_fw_version;
770 caps->driver_version.major = wifi_pos_obj->driver_version.major;
771 caps->driver_version.minor = wifi_pos_obj->driver_version.minor;
772 caps->driver_version.patch = wifi_pos_obj->driver_version.patch;
773 caps->driver_version.build = wifi_pos_obj->driver_version.build;
774 caps->allowed_dwell_time_min = wifi_pos_obj->allowed_dwell_time_min;
775 caps->allowed_dwell_time_max = wifi_pos_obj->allowed_dwell_time_max;
776 caps->curr_dwell_time_min = wifi_pos_obj->current_dwell_time_min;
777 caps->curr_dwell_time_max = wifi_pos_obj->current_dwell_time_max;
778 caps->supported_bands = wlan_objmgr_psoc_get_band_capability(psoc);
Naveen Rawat0b448282017-11-10 10:51:20 -0800779 wifi_pos_get_ch_info(psoc, caps);
Naveen Rawata8423162017-03-06 15:59:31 -0800780 return QDF_STATUS_SUCCESS;
781}