qcacld-3.0: get tsf from fw
qcacld-2.0 to qcacld-3.0 propagation
Get tsf from fw. Provide ioctl interface cap_tsf/get_tsf.
Driver issue wmi cmd to fw to realize capture/get.
It can be used in station and softap mode. For sta, getting
tsf from connected ap. For softap, it will generate tsf by-
self
Change-Id: I00d30882bce2f49ee3de3fa189e094c04c0d9943
CRs-Fixed: 817527
diff --git a/Kbuild b/Kbuild
index 1031b35..11eed09 100755
--- a/Kbuild
+++ b/Kbuild
@@ -377,6 +377,10 @@
HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_tdls.o
endif
+ifeq ($(CONFIG_WLAN_SYNC_TSF),y)
+HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_tsf.o
+endif
+
ifeq ($(CONFIG_MPC_UT_FRAMEWORK),y)
HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_conc_ut.o
endif
@@ -1360,6 +1364,10 @@
CDEFINES += -DLINUX_QCMBR
endif
+# Enable featue sync tsf between multi devices
+ifeq ($(CONFIG_WLAN_SYNC_TSF), y)
+CDEFINES += -DWLAN_FEATURE_TSF
+endif
# Enable full rx re-order offload for adrastea
ifeq (y, $(filter y, $(CONFIG_CNSS_ADRASTEA) $(CONFIG_ICNSS)))
diff --git a/Kconfig b/Kconfig
index 7155ea2..39b64ed 100644
--- a/Kconfig
+++ b/Kconfig
@@ -107,6 +107,10 @@
bool "Enable RX wake lock feature"
default n
+config WLAN_SYNC_TSF
+ bool "Enable QCOM sync multi devices tsf feature"
+ default n
+
config FEATURE_LFR_SUBNET_DETECTION
bool "Enable LFR Subnet Change Detection"
default n
diff --git a/core/hdd/inc/qc_sap_ioctl.h b/core/hdd/inc/qc_sap_ioctl.h
index 5a1bfbe..cede160 100644
--- a/core/hdd/inc/qc_sap_ioctl.h
+++ b/core/hdd/inc/qc_sap_ioctl.h
@@ -131,42 +131,43 @@
* (regardless of the incorrect comment in wireless.h!)
*/
-#define QCSAP_IOCTL_SETPARAM (SIOCIWFIRSTPRIV+0)
-#define QCSAP_IOCTL_GETPARAM (SIOCIWFIRSTPRIV+1)
+#define QCSAP_IOCTL_SETPARAM (SIOCIWFIRSTPRIV + 0)
+#define QCSAP_IOCTL_GETPARAM (SIOCIWFIRSTPRIV + 1)
/* (SIOCIWFIRSTPRIV+2) is unused */
-/* (SIOCIWFIRSTPRIV+3) is unused */
-#define QCSAP_IOCTL_GET_STAWPAIE (SIOCIWFIRSTPRIV+4)
-#define QCSAP_IOCTL_SETWPAIE (SIOCIWFIRSTPRIV+5)
-#define QCSAP_IOCTL_STOPBSS (SIOCIWFIRSTPRIV+6)
-#define QCSAP_IOCTL_VERSION (SIOCIWFIRSTPRIV+7)
-#define QCSAP_IOCTL_GET_WPS_PBC_PROBE_REQ_IES (SIOCIWFIRSTPRIV+8)
-#define QCSAP_IOCTL_GET_CHANNEL (SIOCIWFIRSTPRIV+9)
-#define QCSAP_IOCTL_ASSOC_STA_MACADDR (SIOCIWFIRSTPRIV+10)
-#define QCSAP_IOCTL_DISASSOC_STA (SIOCIWFIRSTPRIV+11)
+#define QCSAP_IOCTL_SET_NONE_GET_THREE (SIOCIWFIRSTPRIV + 3)
+#define WE_GET_TSF 1
+#define QCSAP_IOCTL_GET_STAWPAIE (SIOCIWFIRSTPRIV + 4)
+#define QCSAP_IOCTL_SETWPAIE (SIOCIWFIRSTPRIV + 5)
+#define QCSAP_IOCTL_STOPBSS (SIOCIWFIRSTPRIV + 6)
+#define QCSAP_IOCTL_VERSION (SIOCIWFIRSTPRIV + 7)
+#define QCSAP_IOCTL_GET_WPS_PBC_PROBE_REQ_IES (SIOCIWFIRSTPRIV + 8)
+#define QCSAP_IOCTL_GET_CHANNEL (SIOCIWFIRSTPRIV + 9)
+#define QCSAP_IOCTL_ASSOC_STA_MACADDR (SIOCIWFIRSTPRIV + 10)
+#define QCSAP_IOCTL_DISASSOC_STA (SIOCIWFIRSTPRIV + 11)
/* (SIOCIWFIRSTPRIV+12) is unused */
/* Private ioctls and their sub-ioctls */
#define QCSAP_PRIV_GET_CHAR_SET_NONE (SIOCIWFIRSTPRIV + 13)
#define QCSAP_GET_STATS 1
#define QCSAP_LIST_FW_PROFILE 2
-#define QCSAP_IOCTL_CLR_STATS (SIOCIWFIRSTPRIV+14)
+#define QCSAP_IOCTL_CLR_STATS (SIOCIWFIRSTPRIV + 14)
-#define QCSAP_IOCTL_PRIV_SET_THREE_INT_GET_NONE (SIOCIWFIRSTPRIV+15)
+#define QCSAP_IOCTL_PRIV_SET_THREE_INT_GET_NONE (SIOCIWFIRSTPRIV + 15)
#define WE_SET_WLAN_DBG 1
#define WE_SET_DP_TRACE 2
#define WE_SET_SAP_CHANNELS 3
-#define QCSAP_IOCTL_PRIV_SET_VAR_INT_GET_NONE (SIOCIWFIRSTPRIV+16)
+#define QCSAP_IOCTL_PRIV_SET_VAR_INT_GET_NONE (SIOCIWFIRSTPRIV + 16)
#define WE_UNIT_TEST_CMD 7
-#define QCSAP_IOCTL_SET_CHANNEL_RANGE (SIOCIWFIRSTPRIV+17)
+#define QCSAP_IOCTL_SET_CHANNEL_RANGE (SIOCIWFIRSTPRIV + 17)
#define WE_P2P_NOA_CMD 2
-#define QCSAP_IOCTL_MODIFY_ACL (SIOCIWFIRSTPRIV+18)
-#define QCSAP_IOCTL_GET_CHANNEL_LIST (SIOCIWFIRSTPRIV+19)
-#define QCSAP_IOCTL_SET_TX_POWER (SIOCIWFIRSTPRIV+20)
-#define QCSAP_IOCTL_GET_STA_INFO (SIOCIWFIRSTPRIV+21)
-#define QCSAP_IOCTL_SET_MAX_TX_POWER (SIOCIWFIRSTPRIV+22)
-#define QCSAP_IOCTL_GET_INI_CFG (SIOCIWFIRSTPRIV+25)
-#define QCSAP_IOCTL_SET_INI_CFG (SIOCIWFIRSTPRIV+26)
+#define QCSAP_IOCTL_MODIFY_ACL (SIOCIWFIRSTPRIV + 18)
+#define QCSAP_IOCTL_GET_CHANNEL_LIST (SIOCIWFIRSTPRIV + 19)
+#define QCSAP_IOCTL_SET_TX_POWER (SIOCIWFIRSTPRIV + 20)
+#define QCSAP_IOCTL_GET_STA_INFO (SIOCIWFIRSTPRIV + 21)
+#define QCSAP_IOCTL_SET_MAX_TX_POWER (SIOCIWFIRSTPRIV + 22)
+#define QCSAP_IOCTL_GET_INI_CFG (SIOCIWFIRSTPRIV + 25)
+#define QCSAP_IOCTL_SET_INI_CFG (SIOCIWFIRSTPRIV + 26)
#define QCSAP_IOCTL_SET_TWO_INT_GET_NONE (SIOCIWFIRSTPRIV + 28)
#ifdef DEBUG
#define QCSAP_IOCTL_SET_FW_CRASH_INJECT 1
@@ -241,7 +242,9 @@
QCASAP_CLEAR_STATS,
QCASAP_SET_RADAR_DBG,
QCSAP_GET_FW_PROFILE_DATA,
- QCSAP_START_FW_PROFILING
+ QCSAP_START_FW_PROFILING,
+ QCSAP_CAP_TSF,
+ QCSAP_GET_TSF,
};
int iw_softap_get_channel_list(struct net_device *dev,
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h
index 39fe7e1..ab3873a 100644
--- a/core/hdd/inc/wlan_hdd_main.h
+++ b/core/hdd/inc/wlan_hdd_main.h
@@ -57,6 +57,7 @@
#ifdef FEATURE_WLAN_TDLS
#include "wlan_hdd_tdls.h"
#endif
+#include "wlan_hdd_tsf.h"
#include "wlan_hdd_cfg80211.h"
#include <qdf_defer.h>
#ifdef WLAN_FEATURE_MBSSID
@@ -940,6 +941,14 @@
hdd_ap_ctx_t ap;
} sessionCtx;
+#ifdef WLAN_FEATURE_TSF
+ /* tsf value received from firmware */
+ uint32_t tsf_low;
+ uint32_t tsf_high;
+ /* TSF capture state */
+ enum hdd_tsf_capture_state tsf_state;
+#endif
+
hdd_cfg80211_state_t cfg80211State;
#ifdef WLAN_FEATURE_PACKET_FILTERING
diff --git a/core/hdd/inc/wlan_hdd_tsf.h b/core/hdd/inc/wlan_hdd_tsf.h
new file mode 100644
index 0000000..f251327
--- /dev/null
+++ b/core/hdd/inc/wlan_hdd_tsf.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2016 The Linux Foundation. All rights reserved.
+ *
+ * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
+ *
+ *
+ * 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.
+ */
+
+/*
+ * This file was originally distributed by Qualcomm Atheros, Inc.
+ * under proprietary terms before Copyright ownership was assigned
+ * to the Linux Foundation.
+ */
+
+#if !defined WLAN_HDD_TSF_H
+#define WLAN_HDD_TSF_H
+
+/**
+ * enum hdd_tsf_get_state - status of get tsf action
+ * @TSF_RETURN: get tsf
+ * @TSF_STA_NOT_CONNECTED_NO_TSF: sta not connected to ap
+ * @TSF_NOT_RETURNED_BY_FW: fw not returned tsf
+ * @TSF_CURRENT_IN_CAP_STATE: driver in capture state
+ * @TSF_CAPTURE_FAIL: capture fail
+ * @TSF_GET_FAIL: get fail
+ * @TSF_RESET_GPIO_FAIL: GPIO reset fail
+ * @TSF_SAP_NOT_STARTED_NO_TSF SAP not started
+ */
+enum hdd_tsf_get_state {
+ TSF_RETURN = 0,
+ TSF_STA_NOT_CONNECTED_NO_TSF,
+ TSF_NOT_RETURNED_BY_FW,
+ TSF_CURRENT_IN_CAP_STATE,
+ TSF_CAPTURE_FAIL,
+ TSF_GET_FAIL,
+ TSF_RESET_GPIO_FAIL,
+ TSF_SAP_NOT_STARTED_NO_TSF
+};
+
+/**
+ * enum hdd_tsf_capture_state - status of capture
+ * @TSF_IDLE: idle
+ * @TSF_CAP_STATE: current is in capture state
+ */
+enum hdd_tsf_capture_state {
+ TSF_IDLE = 0,
+ TSF_CAP_STATE
+};
+
+#ifdef WLAN_FEATURE_TSF
+void wlan_hdd_tsf_init(struct hdd_context_s *hdd_ctx);
+int hdd_capture_tsf(struct hdd_adapter_s *adapter, uint32_t *buf, int len);
+int hdd_indicate_tsf(struct hdd_adapter_s *adapter, uint32_t *buf, int len);
+#else
+static inline void wlan_hdd_tsf_init(struct hdd_context_s *hdd_ctx)
+{
+ return;
+}
+
+static inline int hdd_indicate_tsf(struct hdd_adapter_s *adapter, uint32_t *buf,
+ int len)
+{
+ return -ENOTSUPP;
+}
+
+static inline int
+hdd_capture_tsf(struct hdd_adapter_s *adapter, uint32_t *buf, int len)
+{
+ return -ENOTSUPP;
+}
+#endif
+
+#endif
diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c
index 3e5e640..597d512 100644
--- a/core/hdd/src/wlan_hdd_hostapd.c
+++ b/core/hdd/src/wlan_hdd_hostapd.c
@@ -75,6 +75,7 @@
#include "qdf_trace.h"
#include "wlan_hdd_cfg.h"
#include "cds_concurrency.h"
+#include "wlan_hdd_tsf.h"
#include "wlan_hdd_green_ap.h"
#define IS_UP(_dev) \
@@ -3011,6 +3012,66 @@
return ret;
}
+/**
+ * __iw_softap_get_three() - return three value to upper layer.
+ * @dev: pointer of net_device of this wireless card
+ * @info: meta data about Request sent
+ * @wrqu: include request info
+ * @extra: buf used for in/out
+ *
+ * Return: execute result
+ */
+static int __iw_softap_get_three(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ uint32_t *value = (uint32_t *)extra;
+ uint32_t sub_cmd = value[0];
+ int ret = 0; /* success */
+ struct hdd_context_s *hdd_ctx;
+ struct hdd_adapter_s *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+
+ hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+ ret = wlan_hdd_validate_context(hdd_ctx);
+ if (ret != 0)
+ return ret;
+
+ switch (sub_cmd) {
+ case QCSAP_GET_TSF:
+ ret = hdd_indicate_tsf(adapter, value, 3);
+ break;
+ default:
+ hdd_err(FL("Invalid getparam command %d"), sub_cmd);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+
+/**
+ * iw_softap_get_three() - return three value to upper layer.
+ *
+ * @dev: pointer of net_device of this wireless card
+ * @info: meta data about Request sent
+ * @wrqu: include request info
+ * @extra: buf used for in/Output
+ *
+ * Return: execute result
+ */
+static int iw_softap_get_three(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret;
+
+ cds_ssr_protect(__func__);
+ ret = __iw_softap_get_three(dev, info, wrqu, extra);
+ cds_ssr_unprotect(__func__);
+
+ return ret;
+}
+
int
static iw_softap_setparam(struct net_device *dev,
struct iw_request_info *info,
@@ -3211,6 +3272,9 @@
VDEV_CMD);
break;
}
+ case QCSAP_CAP_TSF:
+ ret = hdd_capture_tsf(pHostapdAdapter, (uint32_t *)value, 1);
+ break;
case QCASAP_GET_TEMP_CMD:
{
hddLog(LOG1, "QCASAP_GET_TEMP_CMD");
@@ -5822,6 +5886,15 @@
QCASAP_NSS_CMD, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
"get_nss"
}, {
+ QCSAP_CAP_TSF, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "cap_tsf"
+ }, {
+ QCSAP_IOCTL_SET_NONE_GET_THREE, 0, IW_PRIV_TYPE_INT |
+ IW_PRIV_SIZE_FIXED | 3, ""
+ }, {
+ QCSAP_GET_TSF, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
+ "get_tsf"
+ }, {
QCASAP_GET_TEMP_CMD, 0,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_temp"
}, {
@@ -5997,6 +6070,8 @@
[QCSAP_IOCTL_SETPARAM - SIOCIWFIRSTPRIV] = iw_softap_setparam,
/* get priv ioctl */
[QCSAP_IOCTL_GETPARAM - SIOCIWFIRSTPRIV] = iw_softap_getparam,
+ [QCSAP_IOCTL_SET_NONE_GET_THREE - SIOCIWFIRSTPRIV] =
+ iw_softap_get_three,
/* get station genIE */
[QCSAP_IOCTL_GET_STAWPAIE - SIOCIWFIRSTPRIV] = iw_get_genie,
[QCSAP_IOCTL_SETWPAIE - SIOCIWFIRSTPRIV] = iw_softap_setwpsie,
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index acf6f9d..730ee4e 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -101,6 +101,7 @@
#include "hif.h"
#include "wma.h"
#include "cds_concurrency.h"
+#include "wlan_hdd_tsf.h"
#include "wlan_hdd_green_ap.h"
#include "platform_icnss.h"
#include "bmi.h"
@@ -5963,7 +5964,7 @@
hdd_rssi_threshold_breached);
hdd_cfg80211_link_layer_stats_init(hdd_ctx);
-
+ wlan_hdd_tsf_init(hdd_ctx);
wlan_hdd_send_all_scan_intf_info(hdd_ctx);
wlan_hdd_send_version_pkg(hdd_ctx->target_fw_version,
hdd_ctx->target_hw_version,
diff --git a/core/hdd/src/wlan_hdd_tsf.c b/core/hdd/src/wlan_hdd_tsf.c
new file mode 100644
index 0000000..2563a94
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_tsf.c
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2016 The Linux Foundation. All rights reserved.
+ *
+ * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
+ *
+ *
+ * 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.
+ */
+
+/*
+ * This file was originally distributed by Qualcomm Atheros, Inc.
+ * under proprietary terms before Copyright ownership was assigned
+ * to the Linux Foundation.
+ */
+
+/**
+ * wlan_hdd_tsf.c - WLAN Host Device Driver tsf related implementation
+ */
+
+#include "wlan_hdd_main.h"
+#include "wma_api.h"
+
+/**
+ * hdd_capture_tsf() - capture tsf
+ * @adapter: pointer to adapter
+ * @buf: pointer to uplayer buf
+ * @len : the length of buf
+ *
+ * This function returns tsf value to uplayer.
+ *
+ * Return: 0 for success or non-zero negative failure code
+ */
+int hdd_capture_tsf(struct hdd_adapter_s *adapter, uint32_t *buf, int len)
+{
+ int ret = 0;
+ hdd_station_ctx_t *hdd_sta_ctx;
+
+ if (adapter == NULL || buf == NULL) {
+ hdd_err(FL("invalid pointer"));
+ return -EINVAL;
+ }
+ if (len != 1)
+ return -EINVAL;
+
+ /* Reset TSF value for new capture */
+ adapter->tsf_high = 0;
+ adapter->tsf_low = 0;
+
+ if (adapter->device_mode == QDF_STA_MODE ||
+ adapter->device_mode == QDF_P2P_CLIENT_MODE) {
+ hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+ if (hdd_sta_ctx->conn_info.connState !=
+ eConnectionState_Associated) {
+
+ hdd_err(FL("failed to cap tsf, not connect with ap"));
+ buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF;
+ return ret;
+ }
+ }
+ if ((adapter->device_mode == QDF_SAP_MODE ||
+ adapter->device_mode == QDF_P2P_GO_MODE) &&
+ !(test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags))) {
+ hdd_err(FL("Soft AP / P2p GO not beaconing"));
+ buf[0] = TSF_SAP_NOT_STARTED_NO_TSF;
+ return ret;
+ }
+ if (adapter->tsf_state == TSF_CAP_STATE) {
+ hdd_err(FL("current in capture state, pls reset"));
+ buf[0] = TSF_CURRENT_IN_CAP_STATE;
+ } else {
+ hdd_info(FL("Send TSF capture to FW"));
+ buf[0] = TSF_RETURN;
+ adapter->tsf_state = TSF_CAP_STATE;
+ ret = wma_cli_set_command((int)adapter->sessionId,
+ (int)GEN_PARAM_CAPTURE_TSF,
+ adapter->sessionId,
+ GEN_CMD);
+
+ if (ret != QDF_STATUS_SUCCESS) {
+ hdd_err(FL("capture fail"));
+ buf[0] = TSF_CAPTURE_FAIL;
+ adapter->tsf_state = TSF_IDLE;
+ }
+ }
+ return ret;
+}
+
+/**
+ * hdd_indicate_tsf() - return tsf to uplayer
+ * @adapter: pointer to adapter
+ * @buf: pointer to uplayer buf
+ * @len : the length of buf
+ *
+ * This function returns tsf value to upper layer.
+ *
+ * Return: 0 for success or non-zero negative failure code
+ */
+int hdd_indicate_tsf(struct hdd_adapter_s *adapter, uint32_t *buf, int len)
+{
+ int ret = 0;
+ hdd_station_ctx_t *hdd_sta_ctx;
+
+ if (adapter == NULL || buf == NULL) {
+ hdd_err(FL("invalid pointer"));
+ return -EINVAL;
+ }
+
+ if (len != 3)
+ return -EINVAL;
+
+ buf[1] = 0;
+ buf[2] = 0;
+ if (adapter->device_mode == QDF_STA_MODE ||
+ adapter->device_mode == QDF_P2P_CLIENT_MODE) {
+ hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+ if (hdd_sta_ctx->conn_info.connState !=
+ eConnectionState_Associated) {
+
+ hdd_info(FL("fail to get tsf, sta in disconnected"));
+ buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF;
+ return ret;
+ }
+ }
+ if ((adapter->device_mode == QDF_SAP_MODE ||
+ adapter->device_mode == QDF_P2P_GO_MODE) &&
+ !(test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags))) {
+ hdd_err(FL("Soft AP / P2p GO not beaconing"));
+ buf[0] = TSF_SAP_NOT_STARTED_NO_TSF;
+ return ret;
+ }
+ if (adapter->tsf_high == 0 && adapter->tsf_low == 0) {
+ hdd_info(FL("TSF value not received"));
+ buf[0] = TSF_NOT_RETURNED_BY_FW;
+ } else {
+ buf[0] = TSF_RETURN;
+ buf[1] = adapter->tsf_low;
+ buf[2] = adapter->tsf_high;
+ adapter->tsf_state = TSF_IDLE;
+
+ ret = wma_cli_set_command((int)adapter->sessionId,
+ (int)GEN_PARAM_RESET_TSF_GPIO,
+ adapter->sessionId,
+ GEN_CMD);
+
+ if (0 != ret) {
+ hdd_err(FL("tsf get fail "));
+ buf[0] = TSF_RESET_GPIO_FAIL;
+ }
+ hdd_info(FL("get tsf cmd,status=%u, tsf_low=%u, tsf_high=%u"),
+ buf[0], buf[1], buf[2]);
+ }
+ return ret;
+}
+
+/**
+ * hdd_get_tsf_cb() - handle tsf callback
+ * @pcb_cxt: pointer to the hdd_contex
+ * @ptsf: pointer to struct stsf
+ *
+ * This function handle the event that reported by firmware at first.
+ * The event contains the vdev_id, current tsf value of this vdev,
+ * tsf value is 64bits, discripted in two varaible tsf_low and tsf_high.
+ * These two values each is uint32.
+ *
+ * Return: 0 for success or non-zero negative failure code
+ */
+static int hdd_get_tsf_cb(void *pcb_cxt, struct stsf *ptsf)
+{
+ struct hdd_context_s *hddctx;
+ struct hdd_adapter_s *adapter;
+ int status;
+
+ if (pcb_cxt == NULL || ptsf == NULL) {
+ hdd_err(FL("HDD context is not valid"));
+ return -EINVAL;
+ }
+
+ hddctx = (struct hdd_context_s *)pcb_cxt;
+ status = wlan_hdd_validate_context(hddctx);
+ if (0 != status) {
+ hdd_err(FL("hdd context is not valid"));
+ return -EINVAL;
+ }
+
+ adapter = hdd_get_adapter_by_vdev(hddctx, ptsf->vdev_id);
+
+ if (NULL == adapter) {
+ hdd_err(FL("failed to find adapter"));
+ return -EINVAL;
+ }
+
+ hdd_info(FL("tsf cb handle event, device_mode is %d"),
+ adapter->device_mode);
+
+ adapter->tsf_low = ptsf->tsf_low;
+ adapter->tsf_high = ptsf->tsf_high;
+
+ hdd_info(FL("hdd_get_tsf_cb sta=%u, tsf_low=%u, tsf_high=%u"),
+ ptsf->vdev_id, ptsf->tsf_low, ptsf->tsf_high);
+ return 0;
+}
+
+/**
+ * wlan_hdd_tsf_init() - set callback to handle tsf value.
+ * @hdd_ctx: pointer to the struct hdd_context_s
+ *
+ * This function set the callback to sme module, the callback will be
+ * called when a tsf event is reported by firmware
+ *
+ * Return: none
+ */
+void wlan_hdd_tsf_init(struct hdd_context_s *hdd_ctx)
+{
+ sme_set_tsfcb(hdd_ctx->hHal, hdd_get_tsf_cb, hdd_ctx);
+}
diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c
index f8f4137..b88b01b 100644
--- a/core/hdd/src/wlan_hdd_wext.c
+++ b/core/hdd/src/wlan_hdd_wext.c
@@ -80,6 +80,7 @@
#include "sme_power_save_api.h"
#include "cds_concurrency.h"
#include "wlan_hdd_conc_ut.h"
+#include "wlan_hdd_tsf.h"
#include "wlan_hdd_ocb.h"
#include "wlan_hdd_napi.h"
#include "cdp_txrx_flow_ctrl_legacy.h"
@@ -273,6 +274,7 @@
#define WE_GET_GTX_MINTPC 53
#define WE_GET_GTX_BWMASK 54
#define WE_GET_TEMPERATURE 56
+#define WE_CAP_TSF 58
/* Private ioctls and their sub-ioctls */
#define WLAN_PRIV_SET_INT_GET_INT (SIOCIWFIRSTPRIV + 2)
@@ -383,7 +385,8 @@
/* (SIOCIWFIRSTPRIV + 10) is currently unused */
/* (SIOCIWFIRSTPRIV + 12) is currently unused */
/* (SIOCIWFIRSTPRIV + 14) is currently unused */
-/* (SIOCIWFIRSTPRIV + 15) is currently unused */
+#define WLAN_PRIV_SET_NONE_GET_THREE_INT (SIOCIWFIRSTPRIV + 15)
+#define WE_GET_TSF 1
/* (SIOCIWFIRSTPRIV + 16) is currently unused */
/* (SIOCIWFIRSTPRIV + 17) is currently unused */
/* (SIOCIWFIRSTPRIV + 19) is currently unused */
@@ -6299,6 +6302,65 @@
}
/**
+ * __iw_setnone_get_threeint() - return three value to up layer.
+ *
+ * @dev: pointer of net_device of this wireless card
+ * @info: meta data about Request sent
+ * @wrqu: include request info
+ * @extra: buf used for in/Output
+ *
+ * Return: execute result
+ */
+static int __iw_setnone_get_threeint(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0; /* success */
+ uint32_t *value = (int *)extra;
+ hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+
+ ENTER_DEV(dev);
+ ret = wlan_hdd_validate_context(hdd_ctx);
+ if (0 != ret)
+ return ret;
+
+ hdd_info(FL("param = %d"), value[0]);
+ switch (value[0]) {
+ case WE_GET_TSF:
+ ret = hdd_indicate_tsf(adapter, value, 3);
+ break;
+ default:
+ hdd_err("Invalid IOCTL get_value command %d", value[0]);
+ break;
+ }
+ return ret;
+}
+
+/**
+ * iw_setnone_get_threeint() - return three value to up layer.
+ *
+ * @dev: pointer of net_device of this wireless card
+ * @info: meta data about Request sent
+ * @wrqu: include request info
+ * @extra: buf used for in/Output
+ *
+ * Return: execute result
+ */
+static int iw_setnone_get_threeint(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret;
+
+ cds_ssr_protect(__func__);
+ ret = __iw_setnone_get_threeint(dev, info, wrqu, extra);
+ cds_ssr_unprotect(__func__);
+
+ return ret;
+}
+
+/**
* iw_setchar_getnone() - Generic "set string" private ioctl handler
* @dev: device upon which the ioctl was received
* @info: ioctl request information
@@ -6914,7 +6976,9 @@
QPOWER_CMD);
break;
}
-
+ case WE_CAP_TSF:
+ ret = hdd_capture_tsf(pAdapter, (uint32_t *)value, 1);
+ break;
case WE_GET_TEMPERATURE:
{
hddLog(QDF_TRACE_LEVEL_INFO, "WE_GET_TEMPERATURE");
@@ -9809,6 +9873,8 @@
[WLAN_PRIV_SET_NONE_GET_NONE - SIOCIWFIRSTPRIV] = iw_setnone_getnone, /* action priv ioctl */
[WLAN_PRIV_SET_VAR_INT_GET_NONE - SIOCIWFIRSTPRIV] =
iw_hdd_set_var_ints_getnone,
+ [WLAN_PRIV_SET_NONE_GET_THREE_INT - SIOCIWFIRSTPRIV] =
+ iw_setnone_get_threeint,
[WLAN_PRIV_ADD_TSPEC - SIOCIWFIRSTPRIV] = iw_add_tspec,
[WLAN_PRIV_DEL_TSPEC - SIOCIWFIRSTPRIV] = iw_del_tspec,
[WLAN_PRIV_GET_TSPEC - SIOCIWFIRSTPRIV] = iw_get_tspec,
@@ -10506,6 +10572,11 @@
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
"get_qnodatapoll"},
+ {WE_CAP_TSF,
+ 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "cap_tsf"},
+
{WE_GET_TEMPERATURE,
0,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
@@ -10565,6 +10636,15 @@
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
0,
"setsapchannels"},
+ /* handlers for main ioctl */
+ {WLAN_PRIV_SET_NONE_GET_THREE_INT,
+ 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
+ "" },
+ {WE_GET_TSF,
+ 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
+ "get_tsf" },
{WE_SET_DUAL_MAC_SCAN_CONFIG,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h
index 5c5ff30..0ffc244 100644
--- a/core/mac/inc/sir_api.h
+++ b/core/mac/inc/sir_api.h
@@ -5564,6 +5564,21 @@
};
/**
+ * struct stsf - the basic stsf structure
+ *
+ * @vdev_id: vdev id
+ * @tsf_low: low 32bits of tsf
+ * @tsf_high: high 32bits of tsf
+ *
+ * driver use this struct to store the tsf info
+ */
+struct stsf {
+ uint32_t vdev_id;
+ uint32_t tsf_low;
+ uint32_t tsf_high;
+};
+
+/**
* struct egap_params - the enhanced green ap params
* @vdev_id: vdev id
* @enable: enable or disable the enhance green ap in firmware
diff --git a/core/mac/inc/wni_api.h b/core/mac/inc/wni_api.h
index 23ab4d2..93aae03 100644
--- a/core/mac/inc/wni_api.h
+++ b/core/mac/inc/wni_api.h
@@ -248,6 +248,7 @@
eWNI_SME_HT40_OBSS_SCAN_IND, /* START and UPDATE OBSS SCAN Indication*/
eWNI_SME_SET_ANTENNA_MODE_REQ,
eWNI_SME_SET_ANTENNA_MODE_RESP,
+ eWNI_SME_TSF_EVENT,
eWNI_SME_MSG_TYPES_END
};
diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h
index d836a36..73ce120 100644
--- a/core/sme/inc/sme_api.h
+++ b/core/sme/inc/sme_api.h
@@ -1096,6 +1096,8 @@
void sme_update_fine_time_measurement_capab(tHalHandle hal, uint32_t val);
QDF_STATUS sme_ht40_stop_obss_scan(tHalHandle hHal, uint32_t vdev_id);
+QDF_STATUS sme_set_tsfcb(tHalHandle hHal,
+ int (*cb_fn)(void *cb_ctx, struct stsf *ptsf), void *cb_ctx);
QDF_STATUS sme_update_mimo_power_save(tHalHandle hHal,
uint8_t is_ht_smps_enabled,
diff --git a/core/sme/inc/sme_internal.h b/core/sme/inc/sme_internal.h
index 9e27ba2..f681208 100644
--- a/core/sme/inc/sme_internal.h
+++ b/core/sme/inc/sme_internal.h
@@ -197,6 +197,8 @@
bool enableSelfRecovery;
tCsrLinkStatusCallback linkStatusCallback;
void *linkStatusContext;
+ int (*get_tsf_cb)(void *pcb_cxt, struct stsf *ptsf);
+ void *get_tsf_cxt;
/* get temperature event context and callback */
void *pTemperatureCbContext;
void (*pGetTemperatureCb)(int temperature, void *context);
diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c
index c12aef8..8785b0b 100644
--- a/core/sme/src/common/sme_api.c
+++ b/core/sme/src/common/sme_api.c
@@ -2805,6 +2805,14 @@
qdf_mem_free(pMsg->bodyptr);
}
break;
+ case eWNI_SME_TSF_EVENT:
+ if (pMac->sme.get_tsf_cb) {
+ pMac->sme.get_tsf_cb(pMac->sme.get_tsf_cxt,
+ (struct stsf *)pMsg->bodyptr);
+ }
+ if (pMsg->bodyptr)
+ qdf_mem_free(pMsg->bodyptr);
+ break;
#ifdef WLAN_FEATURE_NAN
case eWNI_SME_NAN_EVENT:
if (pMsg->bodyptr) {
@@ -7300,6 +7308,29 @@
#endif /* FEATURE_WLAN_SCAN_PNO */
+/*
+ * sme_set_tsfcb() - Set callback for TSF capture
+ * @hHal: Handler return by macOpen
+ * @cb_fn: Callback function pointer
+ * @db_ctx: Callback data
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS sme_set_tsfcb(tHalHandle hHal,
+ int (*cb_fn)(void *cb_ctx, struct stsf *ptsf), void *cb_ctx)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ QDF_STATUS status;
+
+ status = sme_acquire_global_lock(&pMac->sme);
+ if (QDF_IS_STATUS_SUCCESS(status)) {
+ pMac->sme.get_tsf_cb = cb_fn;
+ pMac->sme.get_tsf_cxt = cb_ctx;
+ sme_release_global_lock(&pMac->sme);
+ }
+ return status;
+}
+
QDF_STATUS sme_get_cfg_valid_channels(tHalHandle hHal, uint8_t *aValidChannels,
uint32_t *len)
{
diff --git a/core/wma/inc/wma_api.h b/core/wma/inc/wma_api.h
index cec1e1e..4bf40d2 100644
--- a/core/wma/inc/wma_api.h
+++ b/core/wma/inc/wma_api.h
@@ -65,6 +65,8 @@
GEN_PARAM_DUMP_PCIE_ACCESS_LOG,
#endif
GEN_PARAM_MODULATED_DTIM,
+ GEN_PARAM_CAPTURE_TSF,
+ GEN_PARAM_RESET_TSF_GPIO,
} GEN_PARAM;
#define VDEV_CMD 1
diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h
index 42c2c9d..4543eaa 100644
--- a/core/wma/inc/wma_internal.h
+++ b/core/wma/inc/wma_internal.h
@@ -1072,6 +1072,10 @@
auto_sh_cmd);
#endif
+int wma_vdev_tsf_handler(void *handle, uint8_t *data, uint32_t data_len);
+QDF_STATUS wma_capture_tsf(tp_wma_handle wma_handle, uint32_t vdev_id);
+QDF_STATUS wma_reset_tsf_gpio(tp_wma_handle wma_handle, uint32_t vdev_id);
+
#ifdef WLAN_FEATURE_NAN
QDF_STATUS wma_nan_req(void *wma_ptr, tpNanRequest nan_req);
diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c
index 447aa41..3e526e5 100644
--- a/core/wma/src/wma_features.c
+++ b/core/wma/src/wma_features.c
@@ -267,6 +267,177 @@
wma_post_link_status(pGetLinkStatus, LINK_STATUS_LEGACY);
}
+#ifdef WLAN_FEATURE_TSF
+/**
+ * wma_vdev_tsf_handler() - handle tsf event indicated by FW
+ * @handle: wma context
+ * @data: event buffer
+ * @data len: length of event buffer
+ *
+ * Return: 0 on success
+ */
+int wma_vdev_tsf_handler(void *handle, uint8_t *data, uint32_t data_len)
+{
+ cds_msg_t tsf_msg = {0};
+ WMI_VDEV_TSF_REPORT_EVENTID_param_tlvs *param_buf;
+ wmi_vdev_tsf_report_event_fixed_param *tsf_event;
+ struct stsf *ptsf;
+
+ if (data == NULL) {
+ WMA_LOGE("%s: invalid pointer", __func__);
+ return -EINVAL;
+ }
+ ptsf = qdf_mem_malloc(sizeof(*ptsf));
+ if (NULL == ptsf) {
+ WMA_LOGE("%s: failed to allocate tsf data structure", __func__);
+ return -ENOMEM;
+ }
+
+ param_buf = (WMI_VDEV_TSF_REPORT_EVENTID_param_tlvs *)data;
+ tsf_event = param_buf->fixed_param;
+
+ ptsf->vdev_id = tsf_event->vdev_id;
+ ptsf->tsf_low = tsf_event->tsf_low;
+ ptsf->tsf_high = tsf_event->tsf_high;
+
+ WMA_LOGD("%s: receive WMI_VDEV_TSF_REPORT_EVENTID ", __func__);
+ WMA_LOGD("%s: vdev_id = %u,tsf_low =%u, tsf_high = %u", __func__,
+ ptsf->vdev_id, ptsf->tsf_low, ptsf->tsf_high);
+
+ tsf_msg.type = eWNI_SME_TSF_EVENT;
+ tsf_msg.bodyptr = ptsf;
+ tsf_msg.bodyval = 0;
+
+ if (QDF_STATUS_SUCCESS !=
+ cds_mq_post_message(CDS_MQ_ID_SME, &tsf_msg)) {
+
+ WMA_LOGP("%s: Failed to post eWNI_SME_TSF_EVENT", __func__);
+ qdf_mem_free(ptsf);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/**
+ * wma_capture_tsf() - send wmi to fw to capture tsf
+ * @wma_handle: wma handler
+ * @vdev_id: vdev id
+ *
+ * Return: wmi send state
+ */
+QDF_STATUS wma_capture_tsf(tp_wma_handle wma_handle, uint32_t vdev_id)
+{
+ QDF_STATUS status = QDF_STATUS_SUCCESS;
+ wmi_buf_t buf;
+ wmi_vdev_tsf_tstamp_action_cmd_fixed_param *cmd;
+ int ret;
+ int len = sizeof(*cmd);
+
+ buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
+ if (!buf) {
+ WMA_LOGP("%s: failed to allocate memory for cap tsf cmd",
+ __func__);
+ return QDF_STATUS_E_NOMEM;
+ }
+
+ cmd = (wmi_vdev_tsf_tstamp_action_cmd_fixed_param *) wmi_buf_data(buf);
+ cmd->vdev_id = vdev_id;
+ cmd->tsf_action = TSF_TSTAMP_CAPTURE_REQ;
+
+ WMA_LOGD("%s :vdev_id %u, TSF_TSTAMP_CAPTURE_REQ", __func__,
+ cmd->vdev_id);
+
+ WMITLV_SET_HDR(&cmd->tlv_header,
+ WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param,
+ WMITLV_GET_STRUCT_TLVLEN(
+ wmi_vdev_tsf_tstamp_action_cmd_fixed_param));
+
+ ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
+ WMI_VDEV_TSF_TSTAMP_ACTION_CMDID);
+ if (ret != EOK) {
+ WMA_LOGE("wmi_unified_cmd_send returned Error %d", status);
+ status = QDF_STATUS_E_FAILURE;
+ goto error;
+ }
+
+ return QDF_STATUS_SUCCESS;
+
+error:
+ if (buf)
+ wmi_buf_free(buf);
+ return status;
+}
+
+/**
+ * wma_reset_tsf_gpio() - send wmi to fw to reset GPIO
+ * @wma_handle: wma handler
+ * @vdev_id: vdev id
+ *
+ * Return: wmi send state
+ */
+QDF_STATUS wma_reset_tsf_gpio(tp_wma_handle wma_handle, uint32_t vdev_id)
+{
+ QDF_STATUS status = QDF_STATUS_SUCCESS;
+ wmi_buf_t buf;
+ wmi_vdev_tsf_tstamp_action_cmd_fixed_param *cmd;
+ int ret;
+ int len = sizeof(*cmd);
+ uint8_t *buf_ptr;
+
+ buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
+ if (!buf) {
+ WMA_LOGP("%s: failed to allocate memory for reset tsf gpio",
+ __func__);
+ return QDF_STATUS_E_NOMEM;
+ }
+
+ buf_ptr = (uint8_t *) wmi_buf_data(buf);
+ cmd = (wmi_vdev_tsf_tstamp_action_cmd_fixed_param *) buf_ptr;
+ cmd->vdev_id = vdev_id;
+ cmd->tsf_action = TSF_TSTAMP_CAPTURE_RESET;
+
+ WMA_LOGD("%s :vdev_id %u, TSF_TSTAMP_CAPTURE_RESET", __func__,
+ cmd->vdev_id);
+
+ WMITLV_SET_HDR(&cmd->tlv_header,
+ WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param,
+ WMITLV_GET_STRUCT_TLVLEN(
+ wmi_vdev_tsf_tstamp_action_cmd_fixed_param));
+
+ ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len,
+ WMI_VDEV_TSF_TSTAMP_ACTION_CMDID);
+
+ if (ret != EOK) {
+ WMA_LOGE("wmi_unified_cmd_send returned Error %d", status);
+ status = QDF_STATUS_E_FAILURE;
+ goto error;
+ }
+ return QDF_STATUS_SUCCESS;
+
+error:
+ if (buf)
+ wmi_buf_free(buf);
+ return status;
+}
+#else
+QDF_STATUS wma_capture_tsf(tp_wma_handle wma_handle, uint32_t vdev_id)
+{
+ return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS wma_reset_tsf_gpio(tp_wma_handle wma_handle, uint32_t vdev_id)
+{
+ return QDF_STATUS_SUCCESS;
+}
+
+int wma_vdev_tsf_handler(void *handle, uint8_t *data, uint32_t data_len)
+{
+ return 0;
+}
+#endif
+
+
+
#ifdef FEATURE_WLAN_LPHB
/**
* wma_lphb_conf_hbenable() - enable command of LPHB configuration requests
diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c
index 723ff49..b484244 100644
--- a/core/wma/src/wma_main.c
+++ b/core/wma/src/wma_main.c
@@ -919,6 +919,12 @@
privcmd->param_value,
privcmd->param_sec_value);
break;
+ case GEN_PARAM_CAPTURE_TSF:
+ ret = wma_capture_tsf(wma, privcmd->param_value);
+ break;
+ case GEN_PARAM_RESET_TSF_GPIO:
+ ret = wma_reset_tsf_gpio(wma, privcmd->param_value);
+ break;
#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG
case GEN_PARAM_DUMP_PCIE_ACCESS_LOG:
htc_dump(wma->htc_handle, PCIE_DUMP, false);
@@ -2755,6 +2761,16 @@
goto end;
}
+ status = wmi_unified_register_event_handler(wma_handle->wmi_handle,
+ WMI_VDEV_TSF_REPORT_EVENTID,
+ wma_vdev_tsf_handler,
+ WMA_RX_SERIALIZER_CTX);
+ if (0 != status) {
+ WMA_LOGP("%s: Failed to register tsf callback", __func__);
+ qdf_status = QDF_STATUS_E_FAILURE;
+ goto end;
+ }
+
/* Initialize the log flush complete event handler */
status = wmi_unified_register_event_handler(wma_handle->wmi_handle,
WMI_DEBUG_MESG_FLUSH_COMPLETE_EVENTID,