|
@@ -0,0 +1,381 @@
|
|
|
+/*
|
|
|
+ * Copyright (c) 2020, 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.
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * DOC: wlan_hdd_cfr.c
|
|
|
+ *
|
|
|
+ * WLAN Host Device Driver CFR capture Implementation
|
|
|
+ */
|
|
|
+
|
|
|
+#include <linux/version.h>
|
|
|
+#include <linux/module.h>
|
|
|
+#include <linux/kernel.h>
|
|
|
+#include <net/cfg80211.h>
|
|
|
+#include "wlan_hdd_includes.h"
|
|
|
+#include "osif_sync.h"
|
|
|
+#include "wlan_hdd_cfr.h"
|
|
|
+#include "wlan_cfr_ucfg_api.h"
|
|
|
+
|
|
|
+const struct nla_policy cfr_config_policy[
|
|
|
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_MAX + 1] = {
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_CFR_PEER_MAC_ADDR] = {
|
|
|
+ .type = NLA_BINARY, .len = QDF_MAC_ADDR_SIZE},
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE] = {.type = NLA_FLAG},
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_PEER_CFR_BANDWIDTH] = {.type = NLA_U8},
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_PEER_CFR_PERIODICITY] = {.type = NLA_U32},
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD] = {.type = NLA_U8},
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_PEER_CFR_VERSION] = {.type = NLA_U8},
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_PERIODIC_CFR_CAPTURE_ENABLE] = {
|
|
|
+ .type = NLA_FLAG},
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE_GROUP_BITMAP] = {
|
|
|
+ .type = NLA_U32},
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_PEER_CFR_DURATION] = {.type = NLA_U32},
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_PEER_CFR_INTERVAL] = {.type = NLA_U32},
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_TYPE] = {.type = NLA_U32},
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_PEER_CFR_UL_MU_MASK] = {.type = NLA_U64},
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_PEER_CFR_FREEZE_TLV_DELAY_COUNT] = {
|
|
|
+ .type = NLA_U32},
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NUMBER] = {.type = NLA_U32},
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA] = {
|
|
|
+ .type = NLA_BINARY, .len = QDF_MAC_ADDR_SIZE},
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA] = {
|
|
|
+ .type = NLA_BINARY, .len = QDF_MAC_ADDR_SIZE},
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK] = {
|
|
|
+ .type = NLA_BINARY, .len = QDF_MAC_ADDR_SIZE},
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA_MASK] = {
|
|
|
+ .type = NLA_BINARY, .len = QDF_MAC_ADDR_SIZE},
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NSS] = {.type = NLA_U32},
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_BW] = {.type = NLA_U32},
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER] = {
|
|
|
+ .type = NLA_U32},
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER] = {
|
|
|
+ .type = NLA_U32},
|
|
|
+ [QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER] = {
|
|
|
+ .type = NLA_U32},
|
|
|
+};
|
|
|
+
|
|
|
+static QDF_STATUS
|
|
|
+wlan_cfg80211_cfr_set_group_config(struct wlan_objmgr_vdev *vdev,
|
|
|
+ struct nlattr *tb[])
|
|
|
+{
|
|
|
+ struct cfr_wlanconfig_param params = { 0 };
|
|
|
+
|
|
|
+ if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NUMBER]) {
|
|
|
+ params.grp_id = nla_get_u32(tb[
|
|
|
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NUMBER]);
|
|
|
+ hdd_debug("group_id %d", params.grp_id);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (params.grp_id >= HDD_INVALID_GROUP_ID) {
|
|
|
+ hdd_err("invalid group id");
|
|
|
+ return QDF_STATUS_E_INVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA]) {
|
|
|
+ nla_memcpy(¶ms.ta[0],
|
|
|
+ tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA],
|
|
|
+ QDF_MAC_ADDR_SIZE);
|
|
|
+ hdd_debug("ta " QDF_MAC_ADDR_STR,
|
|
|
+ QDF_MAC_ADDR_ARRAY(¶ms.ta[0]));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK]) {
|
|
|
+ nla_memcpy(¶ms.ta_mask[0],
|
|
|
+ tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK],
|
|
|
+ QDF_MAC_ADDR_SIZE);
|
|
|
+ hdd_debug("ta_mask " QDF_MAC_ADDR_STR,
|
|
|
+ QDF_MAC_ADDR_ARRAY(¶ms.ta_mask[0]));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA]) {
|
|
|
+ nla_memcpy(¶ms.ra[0],
|
|
|
+ tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA],
|
|
|
+ QDF_MAC_ADDR_SIZE);
|
|
|
+ hdd_debug("ra " QDF_MAC_ADDR_STR,
|
|
|
+ QDF_MAC_ADDR_ARRAY(¶ms.ra[0]));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA_MASK]) {
|
|
|
+ nla_memcpy(¶ms.ra_mask[0],
|
|
|
+ tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA_MASK],
|
|
|
+ QDF_MAC_ADDR_SIZE);
|
|
|
+ hdd_debug("ra_mask " QDF_MAC_ADDR_STR,
|
|
|
+ QDF_MAC_ADDR_ARRAY(¶ms.ra_mask[0]));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!qdf_is_macaddr_zero((struct qdf_mac_addr *)¶ms.ta) ||
|
|
|
+ !qdf_is_macaddr_zero((struct qdf_mac_addr *)¶ms.ra) ||
|
|
|
+ !qdf_is_macaddr_zero((struct qdf_mac_addr *)¶ms.ta_mask) ||
|
|
|
+ !qdf_is_macaddr_zero((struct qdf_mac_addr *)¶ms.ra_mask)) {
|
|
|
+ hdd_debug("set tara config");
|
|
|
+ ucfg_cfr_set_tara_config(vdev, ¶ms);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NSS]) {
|
|
|
+ params.nss = nla_get_u32(tb[
|
|
|
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NSS]);
|
|
|
+ hdd_debug("nss %d", params.nss);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_BW]) {
|
|
|
+ params.bw = nla_get_u32(tb[
|
|
|
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_BW]);
|
|
|
+ hdd_debug("bw %d", params.bw);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (params.nss || params.bw) {
|
|
|
+ hdd_debug("set bw nss");
|
|
|
+ ucfg_cfr_set_bw_nss(vdev, ¶ms);
|
|
|
+ }
|
|
|
+ if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER]) {
|
|
|
+ params.expected_mgmt_subtype = nla_get_u32(tb[
|
|
|
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER]);
|
|
|
+ hdd_debug("expected_mgmt_subtype %d(%x)",
|
|
|
+ params.expected_mgmt_subtype,
|
|
|
+ params.expected_mgmt_subtype);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER]) {
|
|
|
+ params.expected_ctrl_subtype = nla_get_u32(tb[
|
|
|
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER]);
|
|
|
+ hdd_debug("expected_mgmt_subtype %d(%x)",
|
|
|
+ params.expected_ctrl_subtype,
|
|
|
+ params.expected_ctrl_subtype);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER]) {
|
|
|
+ params.expected_data_subtype = nla_get_u32(tb[
|
|
|
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER]);
|
|
|
+ hdd_debug("expected_mgmt_subtype %d(%x)",
|
|
|
+ params.expected_data_subtype,
|
|
|
+ params.expected_data_subtype);
|
|
|
+ }
|
|
|
+ if (!params.expected_mgmt_subtype ||
|
|
|
+ !params.expected_ctrl_subtype ||
|
|
|
+ !params.expected_data_subtype) {
|
|
|
+ hdd_debug("set frame type");
|
|
|
+ ucfg_cfr_set_frame_type_subtype(vdev, ¶ms);
|
|
|
+ }
|
|
|
+
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+wlan_cfg80211_cfr_set_config(struct wlan_objmgr_vdev *vdev,
|
|
|
+ struct nlattr *tb[])
|
|
|
+{
|
|
|
+ struct nlattr *group[QCA_WLAN_VENDOR_ATTR_PEER_CFR_MAX + 1];
|
|
|
+ struct nlattr *group_list;
|
|
|
+ struct cfr_wlanconfig_param params = { 0 };
|
|
|
+ enum capture_type type;
|
|
|
+ int rem = 0;
|
|
|
+ int maxtype;
|
|
|
+ int attr;
|
|
|
+ uint64_t ul_mu_user_mask = 0;
|
|
|
+
|
|
|
+ if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_DURATION]) {
|
|
|
+ params.cap_dur = nla_get_u32(tb[
|
|
|
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_DURATION]);
|
|
|
+ ucfg_cfr_set_capture_duration(vdev, ¶ms);
|
|
|
+ hdd_debug("params.cap_dur %d", params.cap_dur);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_INTERVAL]) {
|
|
|
+ params.cap_intvl = nla_get_u32(tb[
|
|
|
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_INTERVAL]);
|
|
|
+ ucfg_cfr_set_capture_interval(vdev, ¶ms);
|
|
|
+ hdd_debug("params.cap_intvl %d", params.cap_intvl);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_TYPE]) {
|
|
|
+ type = nla_get_u32(tb[
|
|
|
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_TYPE]);
|
|
|
+ ucfg_cfr_set_rcc_mode(vdev, type, 1);
|
|
|
+ hdd_debug("type %d", type);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_UL_MU_MASK]) {
|
|
|
+ ul_mu_user_mask = nla_get_u64(tb[
|
|
|
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_UL_MU_MASK]);
|
|
|
+ hdd_debug("ul_mu_user_mask_lower %d",
|
|
|
+ params.ul_mu_user_mask_lower);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ul_mu_user_mask) {
|
|
|
+ params.ul_mu_user_mask_lower =
|
|
|
+ (uint32_t)(ul_mu_user_mask & 0xffffffff);
|
|
|
+ params.ul_mu_user_mask_lower =
|
|
|
+ (uint32_t)(ul_mu_user_mask >> 32);
|
|
|
+ hdd_debug("set ul mu user maks");
|
|
|
+ ucfg_cfr_set_ul_mu_user_mask(vdev, ¶ms);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_FREEZE_TLV_DELAY_COUNT]) {
|
|
|
+ params.freeze_tlv_delay_cnt_thr = nla_get_u32(tb[
|
|
|
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_FREEZE_TLV_DELAY_COUNT]);
|
|
|
+ if (params.freeze_tlv_delay_cnt_thr) {
|
|
|
+ params.freeze_tlv_delay_cnt_en = 1;
|
|
|
+ ucfg_cfr_set_freeze_tlv_delay_cnt(vdev, ¶ms);
|
|
|
+ hdd_debug("freeze_tlv_delay_cnt_thr %d",
|
|
|
+ params.freeze_tlv_delay_cnt_thr);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TABLE]) {
|
|
|
+ maxtype = QCA_WLAN_VENDOR_ATTR_PEER_CFR_MAX;
|
|
|
+ attr = QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TABLE;
|
|
|
+ nla_for_each_nested(group_list, tb[attr], rem) {
|
|
|
+ if (wlan_cfg80211_nla_parse(group, maxtype,
|
|
|
+ nla_data(group_list),
|
|
|
+ nla_len(group_list),
|
|
|
+ cfr_config_policy)) {
|
|
|
+ hdd_err("nla_parse failed for cfr config group");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ wlan_cfg80211_cfr_set_group_config(vdev, group);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+wlan_cfg80211_peer_cfr_capture_cfg(struct wiphy *wiphy,
|
|
|
+ struct hdd_adapter *adapter,
|
|
|
+ const void *data,
|
|
|
+ int data_len)
|
|
|
+{
|
|
|
+ struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_MAX + 1];
|
|
|
+ struct cfr_wlanconfig_param params = { 0 };
|
|
|
+ struct wlan_objmgr_vdev *vdev;
|
|
|
+ uint8_t version = 0;
|
|
|
+ bool is_start_capture = false;
|
|
|
+ QDF_STATUS status;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (wlan_cfg80211_nla_parse(
|
|
|
+ tb,
|
|
|
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_MAX,
|
|
|
+ data,
|
|
|
+ data_len,
|
|
|
+ cfr_config_policy)) {
|
|
|
+ hdd_err("Invalid ATTR");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_VERSION]) {
|
|
|
+ version = nla_get_u8(tb[
|
|
|
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_VERSION]);
|
|
|
+ hdd_debug("version %d", version);
|
|
|
+ if (version != ENHANCED_CFR_VERSION) {
|
|
|
+ hdd_err("unsupported version");
|
|
|
+ return -EFAULT;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE]) {
|
|
|
+ is_start_capture = nla_get_flag(tb[
|
|
|
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE]);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (is_start_capture &&
|
|
|
+ !tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE_GROUP_BITMAP]) {
|
|
|
+ hdd_err("Invalid group bitmap");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ vdev = adapter->vdev;
|
|
|
+ status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_CFR_ID);
|
|
|
+ if (QDF_IS_STATUS_ERROR(status)) {
|
|
|
+ hdd_err("can't get vdev");
|
|
|
+ return qdf_status_to_os_return(status);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (is_start_capture) {
|
|
|
+ ret = wlan_cfg80211_cfr_set_config(vdev, tb);
|
|
|
+ if (ret) {
|
|
|
+ hdd_err("set config failed");
|
|
|
+ wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ params.en_cfg = nla_get_u32(tb[
|
|
|
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE_GROUP_BITMAP]);
|
|
|
+ hdd_debug("params.en_cfg %d", params.en_cfg);
|
|
|
+ ucfg_cfr_set_en_bitmap(vdev, ¶ms);
|
|
|
+ } else {
|
|
|
+ hdd_debug("cleanup rcc mode");
|
|
|
+ ucfg_cfr_set_rcc_mode(vdev, RCC_DIS_ALL_MODE, 0);
|
|
|
+ }
|
|
|
+ ucfg_cfr_subscribe_ppdu_desc(wlan_vdev_get_pdev(vdev),
|
|
|
+ is_start_capture);
|
|
|
+ ucfg_cfr_committed_rcc_config(vdev);
|
|
|
+ wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int __wlan_hdd_cfg80211_peer_cfr_capture_cfg(struct wiphy *wiphy,
|
|
|
+ struct wireless_dev *wdev,
|
|
|
+ const void *data,
|
|
|
+ int data_len)
|
|
|
+{
|
|
|
+ int ret;
|
|
|
+ struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
|
|
|
+ struct net_device *dev = wdev->netdev;
|
|
|
+ struct hdd_adapter *adapter;
|
|
|
+
|
|
|
+ hdd_enter();
|
|
|
+
|
|
|
+ ret = wlan_hdd_validate_context(hdd_ctx);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
|
|
|
+ hdd_err("Command not allowed in FTM mode");
|
|
|
+ return -EPERM;
|
|
|
+ }
|
|
|
+
|
|
|
+ adapter = WLAN_HDD_GET_PRIV_PTR(dev);
|
|
|
+ if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ wlan_cfg80211_peer_cfr_capture_cfg(wiphy, adapter,
|
|
|
+ data, data_len);
|
|
|
+
|
|
|
+ hdd_exit();
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+int wlan_hdd_cfg80211_peer_cfr_capture_cfg(struct wiphy *wiphy,
|
|
|
+ struct wireless_dev *wdev,
|
|
|
+ const void *data,
|
|
|
+ int data_len)
|
|
|
+{
|
|
|
+ struct osif_psoc_sync *psoc_sync;
|
|
|
+ int errno;
|
|
|
+
|
|
|
+ errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
|
|
|
+ if (errno)
|
|
|
+ return errno;
|
|
|
+
|
|
|
+ errno = __wlan_hdd_cfg80211_peer_cfr_capture_cfg(wiphy, wdev,
|
|
|
+ data, data_len);
|
|
|
+
|
|
|
+ osif_psoc_sync_op_stop(psoc_sync);
|
|
|
+
|
|
|
+ return errno;
|
|
|
+}
|