|
@@ -0,0 +1,273 @@
|
|
|
+/*
|
|
|
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
|
|
+ *
|
|
|
+ * Permission to use, copy, modify, and/or distribute this software for any
|
|
|
+ * purpose with or without fee is hereby granted, provided that the above
|
|
|
+ * copyright notice and this permission notice appear in all copies.
|
|
|
+ *
|
|
|
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
+ */
|
|
|
+
|
|
|
+#include <osdep.h>
|
|
|
+#include "wmi.h"
|
|
|
+#include "wmi_unified_priv.h"
|
|
|
+#include "wmi_unified_cfr_param.h"
|
|
|
+#include "wmi_unified_cfr_api.h"
|
|
|
+
|
|
|
+#ifdef WLAN_CFR_ENABLE
|
|
|
+static QDF_STATUS
|
|
|
+extract_cfr_peer_tx_event_param_tlv(wmi_unified_t wmi_handle, void *evt_buf,
|
|
|
+ wmi_cfr_peer_tx_event_param *peer_tx_event)
|
|
|
+{
|
|
|
+ int idx;
|
|
|
+ WMI_PEER_CFR_CAPTURE_EVENTID_param_tlvs *param_buf;
|
|
|
+ wmi_peer_cfr_capture_event_fixed_param *peer_tx_event_ev;
|
|
|
+ wmi_peer_cfr_capture_event_phase_fixed_param *chain_phase_ev;
|
|
|
+
|
|
|
+ param_buf = (WMI_PEER_CFR_CAPTURE_EVENTID_param_tlvs *)evt_buf;
|
|
|
+ if (!param_buf) {
|
|
|
+ WMI_LOGE("Invalid cfr capture buffer");
|
|
|
+ return QDF_STATUS_E_INVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ peer_tx_event_ev = param_buf->fixed_param;
|
|
|
+ if (!peer_tx_event_ev) {
|
|
|
+ WMI_LOGE("peer cfr capture buffer is null");
|
|
|
+ return QDF_STATUS_E_NULL_VALUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ peer_tx_event->capture_method = peer_tx_event_ev->capture_method;
|
|
|
+ peer_tx_event->vdev_id = peer_tx_event_ev->vdev_id;
|
|
|
+ WMI_MAC_ADDR_TO_CHAR_ARRAY(&peer_tx_event_ev->mac_addr,
|
|
|
+ &peer_tx_event->peer_mac_addr.bytes[0]);
|
|
|
+ peer_tx_event->primary_20mhz_chan =
|
|
|
+ peer_tx_event_ev->chan_mhz;
|
|
|
+ peer_tx_event->bandwidth = peer_tx_event_ev->bandwidth;
|
|
|
+ peer_tx_event->phy_mode = peer_tx_event_ev->phy_mode;
|
|
|
+ peer_tx_event->band_center_freq1 = peer_tx_event_ev->band_center_freq1;
|
|
|
+ peer_tx_event->band_center_freq2 = peer_tx_event_ev->band_center_freq2;
|
|
|
+ peer_tx_event->spatial_streams = peer_tx_event_ev->sts_count;
|
|
|
+ peer_tx_event->correlation_info_1 =
|
|
|
+ peer_tx_event_ev->correlation_info_1;
|
|
|
+ peer_tx_event->correlation_info_2 =
|
|
|
+ peer_tx_event_ev->correlation_info_2;
|
|
|
+ peer_tx_event->status = peer_tx_event_ev->status;
|
|
|
+ peer_tx_event->timestamp_us = peer_tx_event_ev->timestamp_us;
|
|
|
+ peer_tx_event->counter = peer_tx_event_ev->counter;
|
|
|
+ qdf_mem_copy(peer_tx_event->chain_rssi, peer_tx_event_ev->chain_rssi,
|
|
|
+ sizeof(peer_tx_event->chain_rssi));
|
|
|
+
|
|
|
+ chain_phase_ev = param_buf->phase_param;
|
|
|
+ if (chain_phase_ev) {
|
|
|
+ for (idx = 0; idx < WMI_HOST_MAX_CHAINS; idx++) {
|
|
|
+ /* Due to FW's alignment rules, phase information being
|
|
|
+ * passed is 32-bit, out of which only 16 bits is valid.
|
|
|
+ * Remaining bits are all zeroed. So direct mem copy
|
|
|
+ * will not work as it will copy extra zeroes into host
|
|
|
+ * structures.
|
|
|
+ */
|
|
|
+ peer_tx_event->chain_phase[idx] =
|
|
|
+ (0xffff & chain_phase_ev->chain_phase[idx]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+#ifdef WLAN_ENH_CFR_ENABLE
|
|
|
+static void populate_wmi_cfr_param(uint8_t grp_id, struct cfr_rcc_param *rcc,
|
|
|
+ wmi_cfr_filter_group_config *param)
|
|
|
+{
|
|
|
+ struct ta_ra_cfr_cfg *tgt_cfg = NULL;
|
|
|
+
|
|
|
+ WMITLV_SET_HDR(¶m->tlv_header,
|
|
|
+ WMITLV_TAG_STRUC_wmi_cfr_filter_group_config,
|
|
|
+ WMITLV_GET_STRUCT_TLVLEN
|
|
|
+ (wmi_cfr_filter_group_config));
|
|
|
+ tgt_cfg = &rcc->curr[grp_id];
|
|
|
+
|
|
|
+ param->filter_group_id = grp_id;
|
|
|
+ WMI_CFR_GROUP_TA_ADDR_VALID_SET(param->filter_set_valid_mask,
|
|
|
+ tgt_cfg->valid_ta);
|
|
|
+ WMI_CFR_GROUP_TA_ADDR_MASK_VALID_SET(param->filter_set_valid_mask,
|
|
|
+ tgt_cfg->valid_ta_mask);
|
|
|
+ WMI_CFR_GROUP_RA_ADDR_VALID_SET(param->filter_set_valid_mask,
|
|
|
+ tgt_cfg->valid_ra);
|
|
|
+ WMI_CFR_GROUP_RA_ADDR_MASK_VALID_SET(param->filter_set_valid_mask,
|
|
|
+ tgt_cfg->valid_ra_mask);
|
|
|
+ WMI_CFR_GROUP_BW_VALID_SET(param->filter_set_valid_mask,
|
|
|
+ tgt_cfg->valid_bw_mask);
|
|
|
+ WMI_CFR_GROUP_NSS_VALID_SET(param->filter_set_valid_mask,
|
|
|
+ tgt_cfg->valid_nss_mask);
|
|
|
+ WMI_CFR_GROUP_MGMT_SUBTYPE_VALID_SET(param->filter_set_valid_mask,
|
|
|
+ tgt_cfg->valid_mgmt_subtype);
|
|
|
+ WMI_CFR_GROUP_CTRL_SUBTYPE_VALID_SET(param->filter_set_valid_mask,
|
|
|
+ tgt_cfg->valid_ctrl_subtype);
|
|
|
+ WMI_CFR_GROUP_DATA_SUBTYPE_VALID_SET(param->filter_set_valid_mask,
|
|
|
+ tgt_cfg->valid_data_subtype);
|
|
|
+ WMI_CHAR_ARRAY_TO_MAC_ADDR(tgt_cfg->tx_addr,
|
|
|
+ ¶m->ta_addr);
|
|
|
+ WMI_CHAR_ARRAY_TO_MAC_ADDR(tgt_cfg->tx_addr_mask,
|
|
|
+ ¶m->ta_addr_mask);
|
|
|
+ WMI_CHAR_ARRAY_TO_MAC_ADDR(tgt_cfg->rx_addr,
|
|
|
+ ¶m->ra_addr);
|
|
|
+ WMI_CHAR_ARRAY_TO_MAC_ADDR(tgt_cfg->rx_addr_mask,
|
|
|
+ ¶m->ra_addr_mask);
|
|
|
+ WMI_CFR_GROUP_BW_SET(param->bw_nss_filter,
|
|
|
+ tgt_cfg->bw);
|
|
|
+ WMI_CFR_GROUP_NSS_SET(param->bw_nss_filter,
|
|
|
+ tgt_cfg->nss);
|
|
|
+ param->mgmt_subtype_filter = tgt_cfg->mgmt_subtype_filter;
|
|
|
+ param->ctrl_subtype_filter = tgt_cfg->ctrl_subtype_filter;
|
|
|
+ param->data_subtype_filter = tgt_cfg->data_subtype_filter;
|
|
|
+}
|
|
|
+
|
|
|
+static QDF_STATUS send_cfr_rcc_cmd_tlv(wmi_unified_t wmi_handle,
|
|
|
+ struct cfr_rcc_param *rcc)
|
|
|
+{
|
|
|
+ wmi_cfr_capture_filter_cmd_fixed_param *cmd;
|
|
|
+ wmi_cfr_filter_group_config *param;
|
|
|
+ uint8_t *buf_ptr, grp_id;
|
|
|
+ wmi_buf_t buf;
|
|
|
+ uint32_t len;
|
|
|
+ QDF_STATUS status = QDF_STATUS_SUCCESS;
|
|
|
+ struct wmi_ops *ops = wmi_handle->ops;
|
|
|
+
|
|
|
+ len = sizeof(*cmd) + WMI_TLV_HDR_SIZE;
|
|
|
+ len += rcc->num_grp_tlvs * sizeof(wmi_cfr_filter_group_config);
|
|
|
+ buf = wmi_buf_alloc(wmi_handle, len);
|
|
|
+
|
|
|
+ if (!buf) {
|
|
|
+ WMI_LOGE("%s:wmi_buf_alloc failed\n", __func__);
|
|
|
+ return QDF_STATUS_E_NOMEM;
|
|
|
+ }
|
|
|
+
|
|
|
+ buf_ptr = wmi_buf_data(buf);
|
|
|
+ cmd = (wmi_cfr_capture_filter_cmd_fixed_param *)buf_ptr;
|
|
|
+
|
|
|
+ WMITLV_SET_HDR(&cmd->tlv_header,
|
|
|
+ WMITLV_TAG_STRUC_wmi_cfr_capture_filter_cmd_fixed_param,
|
|
|
+ WMITLV_GET_STRUCT_TLVLEN
|
|
|
+ (wmi_cfr_capture_filter_cmd_fixed_param));
|
|
|
+ cmd->pdev_id = ops->convert_pdev_id_host_to_target(wmi_handle,
|
|
|
+ rcc->pdev_id);
|
|
|
+ WMI_CFR_CAPTURE_INTERVAL_SET(cmd->capture_interval,
|
|
|
+ rcc->capture_interval);
|
|
|
+ WMI_CFR_CAPTURE_DURATION_SET(cmd->capture_duration,
|
|
|
+ rcc->capture_duration);
|
|
|
+ WMI_CFR_FILTER_GROUP_BITMAP_SET(cmd->filter_group_bitmap,
|
|
|
+ rcc->filter_group_bitmap);
|
|
|
+ WMI_CFR_UL_MU_USER_UPPER_SET(cmd->ul_mu_user_mask_upper,
|
|
|
+ rcc->ul_mu_user_mask_upper);
|
|
|
+ cmd->ul_mu_user_mask_lower = rcc->ul_mu_user_mask_lower;
|
|
|
+ WMI_CFR_FREEZE_DELAY_CNT_EN_SET(cmd->freeze_tlv_delay_cnt,
|
|
|
+ rcc->freeze_tlv_delay_cnt_en);
|
|
|
+ WMI_CFR_FREEZE_DELAY_CNT_THR_SET(cmd->freeze_tlv_delay_cnt,
|
|
|
+ rcc->freeze_tlv_delay_cnt_thr);
|
|
|
+ WMI_CFR_DIRECTED_FTM_ACK_EN_SET(cmd->filter_type,
|
|
|
+ rcc->m_directed_ftm);
|
|
|
+ WMI_CFR_ALL_FTM_ACK_EN_SET(cmd->filter_type,
|
|
|
+ rcc->m_all_ftm_ack);
|
|
|
+ WMI_CFR_NDPA_NDP_DIRECTED_EN_SET(cmd->filter_type,
|
|
|
+ rcc->m_ndpa_ndp_directed);
|
|
|
+ WMI_CFR_NDPA_NDP_ALL_EN_SET(cmd->filter_type,
|
|
|
+ rcc->m_ndpa_ndp_all);
|
|
|
+ WMI_CFR_TA_RA_TYPE_FILTER_EN_SET(cmd->filter_type,
|
|
|
+ rcc->m_ta_ra_filter);
|
|
|
+ WMI_CFR_ALL_PACKET_EN_SET(cmd->filter_type,
|
|
|
+ rcc->m_all_packet);
|
|
|
+
|
|
|
+ /* TLV indicating array of structures to follow */
|
|
|
+ buf_ptr += sizeof(wmi_cfr_capture_filter_cmd_fixed_param);
|
|
|
+
|
|
|
+ WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
|
|
|
+ rcc->num_grp_tlvs * sizeof(wmi_cfr_filter_group_config));
|
|
|
+
|
|
|
+ if (rcc->num_grp_tlvs) {
|
|
|
+ buf_ptr += WMI_TLV_HDR_SIZE;
|
|
|
+ param = (wmi_cfr_filter_group_config *)buf_ptr;
|
|
|
+
|
|
|
+ for (grp_id = 0; grp_id < MAX_TA_RA_ENTRIES; grp_id++) {
|
|
|
+ if (qdf_test_bit(grp_id,
|
|
|
+ (unsigned long *)
|
|
|
+ &rcc->modified_in_curr_session)) {
|
|
|
+ populate_wmi_cfr_param(grp_id, rcc, param);
|
|
|
+ param++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ status = wmi_unified_cmd_send(wmi_handle, buf, len,
|
|
|
+ WMI_CFR_CAPTURE_FILTER_CMDID);
|
|
|
+ if (status)
|
|
|
+ wmi_buf_free(buf);
|
|
|
+
|
|
|
+ return status;
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+static QDF_STATUS send_peer_cfr_capture_cmd_tlv(wmi_unified_t wmi_handle,
|
|
|
+ struct peer_cfr_params *param)
|
|
|
+{
|
|
|
+ wmi_peer_cfr_capture_cmd_fixed_param *cmd;
|
|
|
+ wmi_buf_t buf;
|
|
|
+ int len = sizeof(*cmd);
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ buf = wmi_buf_alloc(wmi_handle, len);
|
|
|
+ if (!buf) {
|
|
|
+ qdf_print("%s:wmi_buf_alloc failed\n", __func__);
|
|
|
+ return QDF_STATUS_E_NOMEM;
|
|
|
+ }
|
|
|
+
|
|
|
+ cmd = (wmi_peer_cfr_capture_cmd_fixed_param *)wmi_buf_data(buf);
|
|
|
+ WMITLV_SET_HDR(&cmd->tlv_header,
|
|
|
+ WMITLV_TAG_STRUC_wmi_peer_cfr_capture_cmd_fixed_param,
|
|
|
+ WMITLV_GET_STRUCT_TLVLEN
|
|
|
+ (wmi_peer_cfr_capture_cmd_fixed_param));
|
|
|
+
|
|
|
+ WMI_CHAR_ARRAY_TO_MAC_ADDR(param->macaddr, &cmd->mac_addr);
|
|
|
+ cmd->request = param->request;
|
|
|
+ cmd->vdev_id = param->vdev_id;
|
|
|
+ cmd->periodicity = param->periodicity;
|
|
|
+ cmd->bandwidth = param->bandwidth;
|
|
|
+ cmd->capture_method = param->capture_method;
|
|
|
+
|
|
|
+ ret = wmi_unified_cmd_send(wmi_handle, buf, len,
|
|
|
+ WMI_PEER_CFR_CAPTURE_CMDID);
|
|
|
+ if (QDF_IS_STATUS_ERROR(ret)) {
|
|
|
+ WMI_LOGE("Failed to send WMI_PEER_CFR_CAPTURE_CMDID");
|
|
|
+ wmi_buf_free(buf);
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+#ifdef WLAN_ENH_CFR_ENABLE
|
|
|
+static inline void wmi_enh_cfr_attach_tlv(wmi_unified_t wmi_handle)
|
|
|
+{
|
|
|
+ struct wmi_ops *ops = wmi_handle->ops;
|
|
|
+
|
|
|
+ ops->send_cfr_rcc_cmd = send_cfr_rcc_cmd_tlv;
|
|
|
+}
|
|
|
+#else
|
|
|
+static inline void wmi_enh_cfr_attach_tlv(wmi_unified_t wmi_handle)
|
|
|
+{
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+void wmi_cfr_attach_tlv(wmi_unified_t wmi_handle)
|
|
|
+{
|
|
|
+ struct wmi_ops *ops = wmi_handle->ops;
|
|
|
+
|
|
|
+ ops->send_peer_cfr_capture_cmd = send_peer_cfr_capture_cmd_tlv;
|
|
|
+ ops->extract_cfr_peer_tx_event_param =
|
|
|
+ extract_cfr_peer_tx_event_param_tlv;
|
|
|
+ wmi_enh_cfr_attach_tlv(wmi_handle);
|
|
|
+}
|
|
|
+#endif /* WLAN_CFR_ENABLE */
|