wmi_unified_cfr_tlv.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. /*
  2. * Copyright (c) 2019-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. #include <osdep.h>
  17. #include "wmi.h"
  18. #include "wmi_unified_priv.h"
  19. #include "wmi_unified_cfr_param.h"
  20. #include "wmi_unified_cfr_api.h"
  21. #ifdef WLAN_CFR_ENABLE
  22. static QDF_STATUS
  23. extract_cfr_peer_tx_event_param_tlv(wmi_unified_t wmi_handle, void *evt_buf,
  24. wmi_cfr_peer_tx_event_param *peer_tx_event)
  25. {
  26. int idx;
  27. WMI_PEER_CFR_CAPTURE_EVENTID_param_tlvs *param_buf;
  28. wmi_peer_cfr_capture_event_fixed_param *peer_tx_event_ev;
  29. wmi_peer_cfr_capture_event_phase_fixed_param *chain_phase_ev;
  30. param_buf = (WMI_PEER_CFR_CAPTURE_EVENTID_param_tlvs *)evt_buf;
  31. if (!param_buf) {
  32. wmi_err("Invalid cfr capture buffer");
  33. return QDF_STATUS_E_INVAL;
  34. }
  35. peer_tx_event_ev = param_buf->fixed_param;
  36. if (!peer_tx_event_ev) {
  37. wmi_err("peer cfr capture buffer is null");
  38. return QDF_STATUS_E_NULL_VALUE;
  39. }
  40. peer_tx_event->capture_method = peer_tx_event_ev->capture_method;
  41. peer_tx_event->vdev_id = peer_tx_event_ev->vdev_id;
  42. WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_tx_event_ev->mac_addr,
  43. &peer_tx_event->peer_mac_addr.bytes[0]);
  44. peer_tx_event->primary_20mhz_chan =
  45. peer_tx_event_ev->chan_mhz;
  46. peer_tx_event->bandwidth = peer_tx_event_ev->bandwidth;
  47. peer_tx_event->phy_mode = peer_tx_event_ev->phy_mode;
  48. peer_tx_event->band_center_freq1 = peer_tx_event_ev->band_center_freq1;
  49. peer_tx_event->band_center_freq2 = peer_tx_event_ev->band_center_freq2;
  50. peer_tx_event->spatial_streams = peer_tx_event_ev->sts_count;
  51. peer_tx_event->correlation_info_1 =
  52. peer_tx_event_ev->correlation_info_1;
  53. peer_tx_event->correlation_info_2 =
  54. peer_tx_event_ev->correlation_info_2;
  55. peer_tx_event->status = peer_tx_event_ev->status;
  56. peer_tx_event->timestamp_us = peer_tx_event_ev->timestamp_us;
  57. peer_tx_event->counter = peer_tx_event_ev->counter;
  58. qdf_mem_copy(peer_tx_event->chain_rssi, peer_tx_event_ev->chain_rssi,
  59. sizeof(peer_tx_event->chain_rssi));
  60. if (peer_tx_event_ev->cfo_measurement_valid)
  61. peer_tx_event->cfo_measurement =
  62. peer_tx_event_ev->cfo_measurement;
  63. else
  64. peer_tx_event->cfo_measurement = 0;
  65. peer_tx_event->rx_start_ts = peer_tx_event_ev->rx_start_ts;
  66. peer_tx_event->rx_ts_reset = peer_tx_event_ev->rx_ts_reset;
  67. peer_tx_event->mcs_rate =
  68. WMI_CFR_MCS_GET(peer_tx_event_ev->mcs_gi_info);
  69. peer_tx_event->gi_type =
  70. WMI_CFR_GI_TYPE_GET(peer_tx_event_ev->mcs_gi_info);
  71. chain_phase_ev = param_buf->phase_param;
  72. if (chain_phase_ev) {
  73. for (idx = 0; idx < WMI_HOST_MAX_CHAINS; idx++) {
  74. /* Due to FW's alignment rules, phase information being
  75. * passed is 32-bit, out of which only 16 bits is valid.
  76. * Remaining bits are all zeroed. So direct mem copy
  77. * will not work as it will copy extra zeroes into host
  78. * structures.
  79. */
  80. peer_tx_event->chain_phase[idx] =
  81. (0xffff & chain_phase_ev->chain_phase[idx]);
  82. peer_tx_event->agc_gain[idx] =
  83. WMI_UNIFIED_AGC_GAIN_GET(chain_phase_ev, idx);
  84. peer_tx_event->agc_gain_tbl_index[idx] =
  85. WMI_UNIFIED_AGC_GAIN_TBL_IDX_GET(chain_phase_ev,
  86. idx);
  87. }
  88. }
  89. return QDF_STATUS_SUCCESS;
  90. }
  91. #ifdef WLAN_ENH_CFR_ENABLE
  92. static void populate_wmi_cfr_param(uint8_t grp_id, struct cfr_rcc_param *rcc,
  93. wmi_cfr_filter_group_config *param)
  94. {
  95. struct ta_ra_cfr_cfg *tgt_cfg = NULL;
  96. WMITLV_SET_HDR(&param->tlv_header,
  97. WMITLV_TAG_STRUC_wmi_cfr_filter_group_config,
  98. WMITLV_GET_STRUCT_TLVLEN
  99. (wmi_cfr_filter_group_config));
  100. tgt_cfg = &rcc->curr[grp_id];
  101. param->filter_group_id = grp_id;
  102. WMI_CFR_GROUP_TA_ADDR_VALID_SET(param->filter_set_valid_mask,
  103. tgt_cfg->valid_ta);
  104. WMI_CFR_GROUP_TA_ADDR_MASK_VALID_SET(param->filter_set_valid_mask,
  105. tgt_cfg->valid_ta_mask);
  106. WMI_CFR_GROUP_RA_ADDR_VALID_SET(param->filter_set_valid_mask,
  107. tgt_cfg->valid_ra);
  108. WMI_CFR_GROUP_RA_ADDR_MASK_VALID_SET(param->filter_set_valid_mask,
  109. tgt_cfg->valid_ra_mask);
  110. WMI_CFR_GROUP_BW_VALID_SET(param->filter_set_valid_mask,
  111. tgt_cfg->valid_bw_mask);
  112. WMI_CFR_GROUP_NSS_VALID_SET(param->filter_set_valid_mask,
  113. tgt_cfg->valid_nss_mask);
  114. WMI_CFR_GROUP_MGMT_SUBTYPE_VALID_SET(param->filter_set_valid_mask,
  115. tgt_cfg->valid_mgmt_subtype);
  116. WMI_CFR_GROUP_CTRL_SUBTYPE_VALID_SET(param->filter_set_valid_mask,
  117. tgt_cfg->valid_ctrl_subtype);
  118. WMI_CFR_GROUP_DATA_SUBTYPE_VALID_SET(param->filter_set_valid_mask,
  119. tgt_cfg->valid_data_subtype);
  120. WMI_CHAR_ARRAY_TO_MAC_ADDR(tgt_cfg->tx_addr,
  121. &param->ta_addr);
  122. WMI_CHAR_ARRAY_TO_MAC_ADDR(tgt_cfg->tx_addr_mask,
  123. &param->ta_addr_mask);
  124. WMI_CHAR_ARRAY_TO_MAC_ADDR(tgt_cfg->rx_addr,
  125. &param->ra_addr);
  126. WMI_CHAR_ARRAY_TO_MAC_ADDR(tgt_cfg->rx_addr_mask,
  127. &param->ra_addr_mask);
  128. WMI_CFR_GROUP_BW_SET(param->bw_nss_filter,
  129. tgt_cfg->bw);
  130. WMI_CFR_GROUP_NSS_SET(param->bw_nss_filter,
  131. tgt_cfg->nss);
  132. param->mgmt_subtype_filter = tgt_cfg->mgmt_subtype_filter;
  133. param->ctrl_subtype_filter = tgt_cfg->ctrl_subtype_filter;
  134. param->data_subtype_filter = tgt_cfg->data_subtype_filter;
  135. }
  136. static QDF_STATUS send_cfr_rcc_cmd_tlv(wmi_unified_t wmi_handle,
  137. struct cfr_rcc_param *rcc)
  138. {
  139. wmi_cfr_capture_filter_cmd_fixed_param *cmd;
  140. wmi_cfr_filter_group_config *param;
  141. uint8_t *buf_ptr, grp_id;
  142. wmi_buf_t buf;
  143. uint32_t len;
  144. QDF_STATUS status = QDF_STATUS_SUCCESS;
  145. struct wmi_ops *ops = wmi_handle->ops;
  146. len = sizeof(*cmd) + WMI_TLV_HDR_SIZE;
  147. len += rcc->num_grp_tlvs * sizeof(wmi_cfr_filter_group_config);
  148. buf = wmi_buf_alloc(wmi_handle, len);
  149. if (!buf) {
  150. wmi_err("wmi_buf_alloc failed");
  151. return QDF_STATUS_E_NOMEM;
  152. }
  153. buf_ptr = wmi_buf_data(buf);
  154. cmd = (wmi_cfr_capture_filter_cmd_fixed_param *)buf_ptr;
  155. WMITLV_SET_HDR(&cmd->tlv_header,
  156. WMITLV_TAG_STRUC_wmi_cfr_capture_filter_cmd_fixed_param,
  157. WMITLV_GET_STRUCT_TLVLEN
  158. (wmi_cfr_capture_filter_cmd_fixed_param));
  159. cmd->pdev_id = ops->convert_host_pdev_id_to_target(wmi_handle,
  160. rcc->pdev_id);
  161. WMI_CFR_CAPTURE_INTERVAL_SET(cmd->capture_interval,
  162. rcc->capture_interval);
  163. WMI_CFR_CAPTURE_DURATION_SET(cmd->capture_duration,
  164. rcc->capture_duration);
  165. WMI_CFR_CAPTURE_COUNT_SET(cmd->capture_count, rcc->capture_count);
  166. WMI_CFR_CAPTURE_INTERVAL_MODE_SEL_SET(cmd->capture_count,
  167. rcc->capture_intval_mode_sel);
  168. WMI_CFR_FILTER_GROUP_BITMAP_SET(cmd->filter_group_bitmap,
  169. rcc->filter_group_bitmap);
  170. WMI_CFR_UL_MU_USER_UPPER_SET(cmd->ul_mu_user_mask_upper,
  171. rcc->ul_mu_user_mask_upper);
  172. cmd->ul_mu_user_mask_lower = rcc->ul_mu_user_mask_lower;
  173. WMI_CFR_FREEZE_DELAY_CNT_EN_SET(cmd->freeze_tlv_delay_cnt,
  174. rcc->freeze_tlv_delay_cnt_en);
  175. WMI_CFR_FREEZE_DELAY_CNT_THR_SET(cmd->freeze_tlv_delay_cnt,
  176. rcc->freeze_tlv_delay_cnt_thr);
  177. WMI_CFR_DIRECTED_FTM_ACK_EN_SET(cmd->filter_type,
  178. rcc->m_directed_ftm);
  179. WMI_CFR_ALL_FTM_ACK_EN_SET(cmd->filter_type,
  180. rcc->m_all_ftm_ack);
  181. WMI_CFR_NDPA_NDP_DIRECTED_EN_SET(cmd->filter_type,
  182. rcc->m_ndpa_ndp_directed);
  183. WMI_CFR_NDPA_NDP_ALL_EN_SET(cmd->filter_type,
  184. rcc->m_ndpa_ndp_all);
  185. WMI_CFR_TA_RA_TYPE_FILTER_EN_SET(cmd->filter_type,
  186. rcc->m_ta_ra_filter);
  187. WMI_CFR_FILTER_IN_AS_FP_TA_RA_TYPE_SET(cmd->filter_type,
  188. rcc->en_ta_ra_filter_in_as_fp);
  189. WMI_CFR_ALL_PACKET_EN_SET(cmd->filter_type,
  190. rcc->m_all_packet);
  191. /* TLV indicating array of structures to follow */
  192. buf_ptr += sizeof(wmi_cfr_capture_filter_cmd_fixed_param);
  193. WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
  194. rcc->num_grp_tlvs * sizeof(wmi_cfr_filter_group_config));
  195. if (rcc->num_grp_tlvs) {
  196. buf_ptr += WMI_TLV_HDR_SIZE;
  197. param = (wmi_cfr_filter_group_config *)buf_ptr;
  198. for (grp_id = 0; grp_id < MAX_TA_RA_ENTRIES; grp_id++) {
  199. if (qdf_test_bit(grp_id,
  200. &rcc->modified_in_curr_session)) {
  201. populate_wmi_cfr_param(grp_id, rcc, param);
  202. param++;
  203. }
  204. }
  205. }
  206. status = wmi_unified_cmd_send(wmi_handle, buf, len,
  207. WMI_CFR_CAPTURE_FILTER_CMDID);
  208. if (status)
  209. wmi_buf_free(buf);
  210. return status;
  211. }
  212. static QDF_STATUS
  213. extract_cfr_phase_param_tlv(wmi_unified_t wmi_handle,
  214. void *evt_buf,
  215. struct wmi_cfr_phase_delta_param *param)
  216. {
  217. WMI_PDEV_AOA_PHASEDELTA_EVENTID_param_tlvs *param_buf;
  218. wmi_pdev_aoa_phasedelta_evt_fixed_param *phase_event;
  219. param_buf = (WMI_PDEV_AOA_PHASEDELTA_EVENTID_param_tlvs *)evt_buf;
  220. if (!param_buf) {
  221. wmi_err("Invalid cfr aoa phase delta buffer");
  222. return QDF_STATUS_E_INVAL;
  223. }
  224. phase_event = param_buf->fixed_param;
  225. if (!phase_event) {
  226. wmi_err("CFR phase AoA delta buffer is NULL");
  227. return QDF_STATUS_E_NULL_VALUE;
  228. }
  229. param->freq = phase_event->freq;
  230. param->pdev_id = wmi_handle->ops->convert_pdev_id_target_to_host
  231. (wmi_handle, phase_event->pdev_id);
  232. param->max_chains = phase_event->chainInfo & 0xFFFF;
  233. param->chain_phase_mask = (phase_event->chainInfo >> 16) & 0xFFFF;
  234. if ((sizeof(param->ibf_cal_val)) <
  235. (sizeof(phase_event->perChainIbfCalVal))) {
  236. wmi_err("ibf_cal_val can not hold all values from event data");
  237. return QDF_STATUS_E_RANGE;
  238. }
  239. if ((sizeof(param->phase_delta)) <
  240. (sizeof(phase_event->phasedelta))) {
  241. wmi_err("phase_delta can not hold all values from event data");
  242. return QDF_STATUS_E_RANGE;
  243. }
  244. qdf_mem_copy(param->ibf_cal_val,
  245. phase_event->perChainIbfCalVal,
  246. sizeof(param->ibf_cal_val));
  247. qdf_mem_copy(param->phase_delta,
  248. phase_event->phasedelta,
  249. sizeof(param->phase_delta));
  250. return QDF_STATUS_SUCCESS;
  251. }
  252. #endif
  253. static QDF_STATUS send_peer_cfr_capture_cmd_tlv(wmi_unified_t wmi_handle,
  254. struct peer_cfr_params *param)
  255. {
  256. wmi_peer_cfr_capture_cmd_fixed_param *cmd;
  257. wmi_buf_t buf;
  258. int len = sizeof(*cmd);
  259. int ret;
  260. buf = wmi_buf_alloc(wmi_handle, len);
  261. if (!buf) {
  262. qdf_print("%s:wmi_buf_alloc failed\n", __func__);
  263. return QDF_STATUS_E_NOMEM;
  264. }
  265. cmd = (wmi_peer_cfr_capture_cmd_fixed_param *)wmi_buf_data(buf);
  266. WMITLV_SET_HDR(&cmd->tlv_header,
  267. WMITLV_TAG_STRUC_wmi_peer_cfr_capture_cmd_fixed_param,
  268. WMITLV_GET_STRUCT_TLVLEN
  269. (wmi_peer_cfr_capture_cmd_fixed_param));
  270. WMI_CHAR_ARRAY_TO_MAC_ADDR(param->macaddr, &cmd->mac_addr);
  271. cmd->request = param->request;
  272. cmd->vdev_id = param->vdev_id;
  273. cmd->periodicity = param->periodicity;
  274. cmd->bandwidth = param->bandwidth;
  275. cmd->capture_method = param->capture_method;
  276. ret = wmi_unified_cmd_send(wmi_handle, buf, len,
  277. WMI_PEER_CFR_CAPTURE_CMDID);
  278. if (QDF_IS_STATUS_ERROR(ret)) {
  279. wmi_err("Failed to send WMI_PEER_CFR_CAPTURE_CMDID");
  280. wmi_buf_free(buf);
  281. }
  282. return ret;
  283. }
  284. #ifdef WLAN_ENH_CFR_ENABLE
  285. static inline void wmi_enh_cfr_attach_tlv(wmi_unified_t wmi_handle)
  286. {
  287. struct wmi_ops *ops = wmi_handle->ops;
  288. ops->send_cfr_rcc_cmd = send_cfr_rcc_cmd_tlv;
  289. }
  290. #else
  291. static inline void wmi_enh_cfr_attach_tlv(wmi_unified_t wmi_handle)
  292. {
  293. }
  294. #endif
  295. void wmi_cfr_attach_tlv(wmi_unified_t wmi_handle)
  296. {
  297. struct wmi_ops *ops = wmi_handle->ops;
  298. ops->send_peer_cfr_capture_cmd = send_peer_cfr_capture_cmd_tlv;
  299. ops->extract_cfr_peer_tx_event_param =
  300. extract_cfr_peer_tx_event_param_tlv;
  301. ops->extract_cfr_phase_param = extract_cfr_phase_param_tlv;
  302. wmi_enh_cfr_attach_tlv(wmi_handle);
  303. }
  304. #endif /* WLAN_CFR_ENABLE */