summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@quicinc.com>2017-04-25 21:16:15 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2017-04-25 21:16:15 -0700
commit0f4e5eaccdade6a811cd3664aa8e6119fbe066d2 (patch)
treebaf6028695416613cf786df2651862558e119b27
parentc2109fe4614223f86b1d2fdbd3748b2bb581f86f (diff)
parent943abb9e54f2e5b86746e4f8b2250823831c7539 (diff)
Merge "qcacld-2.0: enhance the robustness of TSF capturing" into wlan-cld2.driver.lnx.1.0-dev
-rw-r--r--CORE/HDD/inc/wlan_hdd_main.h13
-rw-r--r--CORE/HDD/inc/wlan_hdd_tsf.h58
-rw-r--r--CORE/HDD/inc/wlan_hdd_wext.h6
-rw-r--r--CORE/HDD/src/wlan_hdd_main.c36
-rw-r--r--CORE/HDD/src/wlan_hdd_tsf.c344
5 files changed, 302 insertions, 155 deletions
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index 64e27800e3e0..e02bca29de64 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -1337,10 +1337,7 @@ struct hdd_adapter_s
#ifdef WLAN_FEATURE_TSF
/* tsf value get from firmware */
- uint32_t tsf_low;
- uint32_t tsf_high;
- /* current in capture tsf state or not */
- enum hdd_tsf_capture_state tsf_state;
+ uint64_t cur_target_time;
#endif
hdd_cfg80211_state_t cfg80211State;
@@ -2099,6 +2096,14 @@ struct hdd_context_s
scan_reject_states last_scan_reject_reason;
v_TIME_t last_scan_reject_timestamp;
uint8_t hdd_dfs_regdomain;
+#ifdef WLAN_FEATURE_TSF
+ /* indicate whether tsf has been initialized */
+ adf_os_atomic_t tsf_ready_flag;
+ /* indicate whether it's now capturing tsf(updating tstamp-pair) */
+ adf_os_atomic_t cap_tsf_flag;
+ /* the context that is capturing tsf */
+ hdd_adapter_t *cap_tsf_context;
+#endif
};
/*---------------------------------------------------------------------------
diff --git a/CORE/HDD/inc/wlan_hdd_tsf.h b/CORE/HDD/inc/wlan_hdd_tsf.h
index c3da0cf8f622..d9ba92cc9662 100644
--- a/CORE/HDD/inc/wlan_hdd_tsf.h
+++ b/CORE/HDD/inc/wlan_hdd_tsf.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015,2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -42,18 +42,68 @@
-------------------------------------------------------------------------*/
#ifdef WLAN_FEATURE_TSF
+
+/**
+ * wlan_hdd_tsf_init() - set gpio and callbacks for
+ * capturing tsf and init tsf_plus
+ * @hdd_ctx: pointer to the hdd_context_t
+ *
+ * This function set the callback to sme module, the callback will be
+ * called when a tsf event is reported by firmware; set gpio number
+ * to FW, FW will toggle this gpio when received a CAP_TSF command;
+ * do tsf_plus init
+ *
+ * Return: nothing
+ */
void wlan_hdd_tsf_init(hdd_context_t *hdd_ctx);
+
+/**
+ * wlan_hdd_tsf_deinit() - reset callbacks for capturing tsf, deinit tsf_plus
+ * @hdd_ctx: pointer to the hdd_context_t
+ *
+ * This function reset the callback to sme module, and deinit tsf_plus
+ *
+ * Return: nothing
+ */
+void wlan_hdd_tsf_deinit(hdd_context_t *hdd_ctx);
+
+/**
+ * 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: Describe the execute result of this routine
+ */
int hdd_capture_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len);
+
+/**
+ * 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 uplayer.
+ *
+ * Return: Describe the execute result of this routine
+ */
int hdd_indicate_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len);
#else
static inline void
wlan_hdd_tsf_init(hdd_context_t *hdd_ctx)
{
- return;
}
-static inline int
-hdd_indicate_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
+static inline void wlan_hdd_tsf_deinit(hdd_context_t *hdd_ctx)
+{
+}
+
+static inline int hdd_indicate_tsf(hdd_adapter_t *adapter,
+ uint32_t *buf, int len)
{
return -ENOTSUPP;
}
diff --git a/CORE/HDD/inc/wlan_hdd_wext.h b/CORE/HDD/inc/wlan_hdd_wext.h
index 67b90725fe47..dac20cc0f39b 100644
--- a/CORE/HDD/inc/wlan_hdd_wext.h
+++ b/CORE/HDD/inc/wlan_hdd_wext.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -257,6 +257,7 @@ typedef enum
* TSF_GET_FAIL: get fail
* TSF_RESET_GPIO_FAIL: GPIO reset fail
* TSF_SAP_NOT_STARTED_NO_TSF SAP not started
+ * TSF_NOT_READY: TSF module is not initialized or init failed
*/
enum hdd_tsf_get_state {
TSF_RETURN = 0,
@@ -266,7 +267,8 @@ enum hdd_tsf_get_state {
TSF_CAPTURE_FAIL,
TSF_GET_FAIL,
TSF_RESET_GPIO_FAIL,
- TSF_SAP_NOT_STARTED_NO_TSF
+ TSF_SAP_NOT_STARTED_NO_TSF,
+ TSF_NOT_READY
};
/**
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index 026d702ba4e5..bdbed1821764 100644
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -13410,6 +13410,8 @@ void hdd_wlan_exit(hdd_context_t *pHddCtx)
hddLog(LOGE, FL("Unregister IPv4 notifier"));
unregister_inetaddr_notifier(&pHddCtx->ipv4_notifier);
+ wlan_hdd_tsf_deinit(pHddCtx);
+
if (VOS_FTM_MODE != hdd_get_conparam())
{
// Unloading, restart logic is no more required.
@@ -14887,36 +14889,6 @@ static int wlan_hdd_set_wakeup_gpio(hdd_context_t *hddctx)
}
/**
- * hdd_tsf_init() - Initialize the TSF synchronization interface
- * @hdd_ctx: HDD global context
- *
- * When TSF synchronization via GPIO is supported by the driver and
- * has been enabled in the configuration file, this function plumbs
- * the GPIO value down to firmware via SME.
- *
- * Return: None
- */
-#ifdef WLAN_FEATURE_TSF
-static void hdd_tsf_init(hdd_context_t *hdd_ctx)
-{
- eHalStatus hal_status;
-
- if (hdd_ctx->cfg_ini->tsf_gpio_pin == TSF_GPIO_PIN_INVALID)
- return;
-
- hal_status = sme_set_tsf_gpio(hdd_ctx->hHal,
- hdd_ctx->cfg_ini->tsf_gpio_pin);
- if (eHAL_STATUS_SUCCESS != hal_status)
- hddLog(LOGE, FL("set tsf GPIO failed, status: %d"),
- hal_status);
-}
-#else
-static void hdd_tsf_init(hdd_context_t *hdd_ctx)
-{
-}
-#endif
-
-/**
* hdd_state_info_dump() - prints state information of hdd layer
* @buf: buffer pointer
* @size: size of buffer to be filled
@@ -16110,7 +16082,6 @@ int hdd_wlan_startup(struct device *dev, v_VOID_t *hif_sc)
"%s: Error setting txlimit in sme", __func__);
}
- hdd_tsf_init(pHddCtx);
vos_timer_init(&pHddCtx->tdls_source_timer, VOS_TIMER_TYPE_SW,
wlan_hdd_change_tdls_mode, (void *)pHddCtx);
@@ -16133,8 +16104,7 @@ int hdd_wlan_startup(struct device *dev, v_VOID_t *hif_sc)
wlan_hdd_cfg80211_chainrssi_callback);
sme_set_rssi_threshold_breached_cb(pHddCtx->hHal, hdd_rssi_threshold_breached);
wlan_hdd_cfg80211_link_layer_stats_init(pHddCtx);
-
- wlan_hdd_tsf_init(pHddCtx);
+ wlan_hdd_tsf_init(pHddCtx);
#ifdef WLAN_FEATURE_LPSS
wlan_hdd_send_all_scan_intf_info(pHddCtx);
diff --git a/CORE/HDD/src/wlan_hdd_tsf.c b/CORE/HDD/src/wlan_hdd_tsf.c
index f9df7b160da6..f328a4450144 100644
--- a/CORE/HDD/src/wlan_hdd_tsf.c
+++ b/CORE/HDD/src/wlan_hdd_tsf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2017 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -30,151 +30,222 @@
*/
#include "wlan_hdd_main.h"
+#include "wlan_hdd_tsf.h"
#include "wma_api.h"
/**
- * hdd_capture_tsf() - capture tsf
+ * enum hdd_tsf_op_result - result of tsf operation
*
- * @adapter: pointer to adapter
- * @buf: pointer to uplayer buf
- * @len : the length of buf
- *
- * This function returns tsf value to uplayer.
- *
- * Return: Describe the execute result of this routine
+ * HDD_TSF_OP_SUCC: succeed
+ * HDD_TSF_OP_FAIL: fail
*/
-int hdd_capture_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
+enum hdd_tsf_op_result {
+ HDD_TSF_OP_SUCC,
+ HDD_TSF_OP_FAIL
+};
+
+static
+enum hdd_tsf_get_state hdd_tsf_check_conn_state(hdd_adapter_t *adapter)
{
- int ret = 0;
+ enum hdd_tsf_get_state ret = TSF_RETURN;
hdd_station_ctx_t *hdd_sta_ctx;
- if (adapter == NULL || buf == NULL) {
- hddLog(VOS_TRACE_LEVEL_ERROR,
- 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 == WLAN_HDD_INFRA_STATION ||
- adapter->device_mode == WLAN_HDD_P2P_CLIENT) {
+ adapter->device_mode == WLAN_HDD_P2P_CLIENT) {
hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
if (hdd_sta_ctx->conn_info.connState !=
- eConnectionState_Associated) {
-
+ eConnectionState_Associated) {
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("failed to cap tsf, not connect with ap"));
- buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF;
- return ret;
+ ret = TSF_STA_NOT_CONNECTED_NO_TSF;
}
- }
- if ((adapter->device_mode == WLAN_HDD_SOFTAP ||
- adapter->device_mode == WLAN_HDD_P2P_GO) &&
- !(test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags))) {
+ } else if ((adapter->device_mode == WLAN_HDD_SOFTAP ||
+ adapter->device_mode == WLAN_HDD_P2P_GO) &&
+ !(test_bit(SOFTAP_BSS_STARTED,
+ &adapter->event_flags))) {
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("Soft AP / P2p GO not beaconing"));
- buf[0] = TSF_SAP_NOT_STARTED_NO_TSF;
- return ret;
+ ret = TSF_SAP_NOT_STARTED_NO_TSF;
}
- if (adapter->tsf_state == TSF_CAP_STATE) {
+ return ret;
+}
+
+static bool hdd_tsf_is_initialized(hdd_adapter_t *adapter)
+{
+ hdd_context_t *hddctx;
+
+ if (!adapter) {
hddLog(VOS_TRACE_LEVEL_ERROR,
- FL("current in capture state, pls reset"));
- buf[0] = TSF_CURRENT_IN_CAP_STATE;
- } else {
- hddLog(VOS_TRACE_LEVEL_INFO, FL("+ioctl issue cap tsf cmd"));
- buf[0] = TSF_RETURN;
- adapter->tsf_state = TSF_CAP_STATE;
- ret = process_wma_set_command((int)adapter->sessionId,
- (int)GEN_PARAM_CAPTURE_TSF,
- adapter->sessionId,
- GEN_CMD);
-
- if (ret != VOS_STATUS_SUCCESS) {
- hddLog(VOS_TRACE_LEVEL_ERROR, FL("capture fail"));
- buf[0] = TSF_CAPTURE_FAIL;
- adapter->tsf_state = TSF_IDLE;
- }
- hddLog(VOS_TRACE_LEVEL_INFO,
- FL("-ioctl return cap tsf cmd, ret = %d"), ret);
+ FL("invalid adapter"));
+ return false;
}
- return ret;
+
+ hddctx = WLAN_HDD_GET_CTX(adapter);
+ if (!hddctx) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("invalid hdd context"));
+ return false;
+ }
+
+ if (!adf_os_atomic_read(&hddctx->tsf_ready_flag)) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("TSF is not initialized"));
+ return false;
+ }
+
+ return true;
}
-/**
- * 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 uplayer.
- *
- * Return: Describe the execute result of this routine
- */
-int hdd_indicate_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
+static inline int hdd_reset_tsf_gpio(hdd_adapter_t *adapter)
{
- int ret = 0;
- hdd_station_ctx_t *hdd_sta_ctx;
+ return process_wma_set_command((int)adapter->sessionId,
+ (int)GEN_PARAM_RESET_TSF_GPIO,
+ adapter->sessionId,
+ GEN_CMD);
+}
+
+static enum hdd_tsf_op_result hdd_capture_tsf_internal(
+ hdd_adapter_t *adapter, uint32_t *buf, int len)
+{
+ int ret;
+ hdd_context_t *hddctx;
if (adapter == NULL || buf == NULL) {
hddLog(VOS_TRACE_LEVEL_ERROR,
- FL("invalid pointer"));
- return -EINVAL;
+ FL("invalid pointer"));
+ return HDD_TSF_OP_FAIL;
+ }
+
+ if (len != 1)
+ return HDD_TSF_OP_FAIL;
+
+ hddctx = WLAN_HDD_GET_CTX(adapter);
+ if (!hddctx) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("invalid hdd context"));
+ return HDD_TSF_OP_FAIL;
+ }
+
+ if (!hdd_tsf_is_initialized(adapter)) {
+ buf[0] = TSF_NOT_READY;
+ return HDD_TSF_OP_SUCC;
+ }
+
+ buf[0] = hdd_tsf_check_conn_state(adapter);
+ if (buf[0] != TSF_RETURN)
+ return HDD_TSF_OP_SUCC;
+
+ if (adf_os_atomic_inc_return(&hddctx->cap_tsf_flag) > 1) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("current in capture state"));
+ buf[0] = TSF_CURRENT_IN_CAP_STATE;
+ return HDD_TSF_OP_SUCC;
+ }
+
+ /* record adapter for cap_tsf_irq_handler */
+ hddctx->cap_tsf_context = adapter;
+
+ hddLog(VOS_TRACE_LEVEL_INFO, FL("+ioctl issue cap tsf cmd"));
+
+ /* Reset TSF value for new capture */
+ adapter->cur_target_time = 0;
+
+ buf[0] = TSF_RETURN;
+ ret = process_wma_set_command((int)adapter->sessionId,
+ (int)GEN_PARAM_CAPTURE_TSF,
+ adapter->sessionId,
+ GEN_CMD);
+
+ if (0 != ret) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, FL("cap tsf fail"));
+ buf[0] = TSF_CAPTURE_FAIL;
+ hddctx->cap_tsf_context = NULL;
+ adf_os_atomic_set(&hddctx->cap_tsf_flag, 0);
+ return HDD_TSF_OP_SUCC;
+ }
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ FL("-ioctl return cap tsf cmd"));
+ return HDD_TSF_OP_SUCC;
+}
+
+static enum hdd_tsf_op_result hdd_indicate_tsf_internal(
+ hdd_adapter_t *adapter, uint32_t *buf, int len)
+{
+ int ret;
+ hdd_context_t *hddctx;
+
+ if (adapter == NULL || buf == NULL) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("invalid pointer"));
+ return HDD_TSF_OP_FAIL;
}
if (len != 3)
- return -EINVAL;
+ return HDD_TSF_OP_FAIL;
+
+ hddctx = WLAN_HDD_GET_CTX(adapter);
+ if (!hddctx) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("invalid hdd context"));
+ return HDD_TSF_OP_FAIL;
+ }
buf[1] = 0;
buf[2] = 0;
- if (adapter->device_mode == WLAN_HDD_INFRA_STATION ||
- adapter->device_mode == WLAN_HDD_P2P_CLIENT) {
- hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
- if (hdd_sta_ctx->conn_info.connState !=
- eConnectionState_Associated) {
- hddLog(VOS_TRACE_LEVEL_INFO,
- FL("fail to get tsf, sta in disconnected"));
- buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF;
- return ret;
- }
+ if (!hdd_tsf_is_initialized(adapter)) {
+ buf[0] = TSF_NOT_READY;
+ return HDD_TSF_OP_SUCC;
}
- if ((adapter->device_mode == WLAN_HDD_SOFTAP ||
- adapter->device_mode == WLAN_HDD_P2P_GO) &&
- !(test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags))) {
- hddLog(VOS_TRACE_LEVEL_ERROR,
- 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) {
+
+ buf[0] = hdd_tsf_check_conn_state(adapter);
+ if (buf[0] != TSF_RETURN)
+ return HDD_TSF_OP_SUCC;
+
+ if (adapter->cur_target_time == 0) {
hddLog(VOS_TRACE_LEVEL_INFO,
- FL("not getting tsf value"));
+ FL("not getting tsf value"));
buf[0] = TSF_NOT_RETURNED_BY_FW;
+ return HDD_TSF_OP_SUCC;
} else {
buf[0] = TSF_RETURN;
- buf[1] = adapter->tsf_low;
- buf[2] = adapter->tsf_high;
- adapter->tsf_state = TSF_IDLE;
+ buf[1] = (uint32_t)(adapter->cur_target_time & 0xffffffff);
+ buf[2] = (uint32_t)((adapter->cur_target_time >> 32) &
+ 0xffffffff);
- ret = process_wma_set_command((int)adapter->sessionId,
- (int)GEN_PARAM_RESET_TSF_GPIO,
- adapter->sessionId,
- GEN_CMD);
+ if (!adf_os_atomic_read(&hddctx->cap_tsf_flag)) {
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ FL("old: status=%u, tsf_low=%u, tsf_high=%u"),
+ buf[0], buf[1], buf[2]);
+ return HDD_TSF_OP_SUCC;
+ }
+ ret = hdd_reset_tsf_gpio(adapter);
if (0 != ret) {
- hddLog(VOS_TRACE_LEVEL_ERROR, FL("tsf get fail "));
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("reset tsf gpio fail"));
buf[0] = TSF_RESET_GPIO_FAIL;
+ return HDD_TSF_OP_SUCC;
}
+ hddctx->cap_tsf_context = NULL;
+ adf_os_atomic_set(&hddctx->cap_tsf_flag, 0);
hddLog(VOS_TRACE_LEVEL_INFO,
FL("get tsf cmd,status=%u, tsf_low=%u, tsf_high=%u"),
buf[0], buf[1], buf[2]);
+ return HDD_TSF_OP_SUCC;
}
- return ret;
+}
+
+int hdd_capture_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
+{
+ return (hdd_capture_tsf_internal(adapter, buf, len) ==
+ HDD_TSF_OP_SUCC ? 0 : -EINVAL);
+}
+
+int hdd_indicate_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
+{
+ return (hdd_indicate_tsf_internal(adapter, buf, len) ==
+ HDD_TSF_OP_SUCC ? 0 : -EINVAL);
}
/**
@@ -215,12 +286,18 @@ static int hdd_get_tsf_cb(void *pcb_cxt, struct stsf *ptsf)
return -EINVAL;
}
+ if (!hdd_tsf_is_initialized(adapter)) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("tsf is not init, ignore tsf event"));
+ return -EINVAL;
+ }
+
hddLog(VOS_TRACE_LEVEL_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;
+ adapter->cur_target_time = ((uint64_t)ptsf->tsf_high << 32 |
+ ptsf->tsf_low);
hddLog(VOS_TRACE_LEVEL_INFO,
FL("hdd_get_tsf_cb sta=%u, tsf_low=%u, tsf_high=%u"),
@@ -228,16 +305,59 @@ static int hdd_get_tsf_cb(void *pcb_cxt, struct stsf *ptsf)
return 0;
}
-/**
- * wlan_hdd_tsf_init() - set callback to handle tsf value.
- * @hdd_ctx: pointer to the hdd_context_t
- *
- * This function set the callback to sme module, the callback will be
- * called when a tsf event is reported by firmware
- *
- * Return: nothing
- */
void wlan_hdd_tsf_init(hdd_context_t *hdd_ctx)
{
- sme_set_tsfcb(hdd_ctx->hHal, hdd_get_tsf_cb, hdd_ctx);
+ eHalStatus hal_status;
+
+ if (!hdd_ctx)
+ return;
+
+ if (adf_os_atomic_inc_return(&hdd_ctx->tsf_ready_flag) > 1)
+ return;
+
+ adf_os_atomic_init(&hdd_ctx->cap_tsf_flag);
+
+ if (hdd_ctx->cfg_ini->tsf_gpio_pin == TSF_GPIO_PIN_INVALID)
+ goto fail;
+
+ hal_status = sme_set_tsf_gpio(hdd_ctx->hHal,
+ hdd_ctx->cfg_ini->tsf_gpio_pin);
+ if (eHAL_STATUS_SUCCESS != hal_status) {
+ hddLog(LOGE, FL("set tsf GPIO failed, status: %d"),
+ hal_status);
+ goto fail;
+ }
+
+ hal_status = sme_set_tsfcb(hdd_ctx->hHal, hdd_get_tsf_cb, hdd_ctx);
+ if (eHAL_STATUS_SUCCESS != hal_status) {
+ hddLog(LOGE, FL("set tsf cb failed, status: %d"),
+ hal_status);
+ goto fail;
+ }
+
+ return;
+
+fail:
+ adf_os_atomic_set(&hdd_ctx->tsf_ready_flag, 0);
+ return;
+}
+
+void wlan_hdd_tsf_deinit(hdd_context_t *hdd_ctx)
+{
+ eHalStatus hal_status;
+
+ if (!hdd_ctx)
+ return;
+
+ if (!adf_os_atomic_read(&hdd_ctx->tsf_ready_flag))
+ return;
+
+ hal_status = sme_set_tsfcb(hdd_ctx->hHal, NULL, NULL);
+ if (eHAL_STATUS_SUCCESS != hal_status) {
+ hddLog(LOGE, FL("reset tsf cb failed, status: %d"),
+ hal_status);
+ }
+
+ adf_os_atomic_set(&hdd_ctx->tsf_ready_flag, 0);
+ adf_os_atomic_set(&hdd_ctx->cap_tsf_flag, 0);
}