summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@quicinc.com>2017-04-25 21:16:17 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2017-04-25 21:16:17 -0700
commitab829079c8edba8d0929c9bd8db93ca1ee929a4e (patch)
tree73b51adc19d3ec29ae3a0369d88b7263adbeded4
parent0f4e5eaccdade6a811cd3664aa8e6119fbe066d2 (diff)
parent7e9fd6e65efa6c334cfe57f365f4037cf8501c53 (diff)
Merge "qcacld-2.0: add support for target-host synchronization" 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.h59
-rw-r--r--CORE/HDD/inc/wlan_hdd_wext.h4
-rw-r--r--CORE/HDD/src/wlan_hdd_assoc.c5
-rw-r--r--CORE/HDD/src/wlan_hdd_tsf.c540
-rw-r--r--Kbuild14
6 files changed, 628 insertions, 7 deletions
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index e02bca29de64..0425476ac21e 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -1338,6 +1338,19 @@ struct hdd_adapter_s
#ifdef WLAN_FEATURE_TSF
/* tsf value get from firmware */
uint64_t cur_target_time;
+
+#ifdef WLAN_FEATURE_TSF_PLUS
+ /* spin lock for read/write timestamps */
+ spinlock_t host_target_sync_lock;
+ vos_timer_t host_target_sync_timer;
+ uint64_t cur_host_time;
+ uint64_t last_host_time;
+ uint64_t last_target_time;
+ /* to store the count of continuous invalid tstamp-pair */
+ int continuous_error_count;
+ /* to indicate whether tsf_sync has been initialized */
+ adf_os_atomic_t tsf_sync_ready_flag;
+#endif /* WLAN_FEATURE_TSF_PLUS */
#endif
hdd_cfg80211_state_t cfg80211State;
diff --git a/CORE/HDD/inc/wlan_hdd_tsf.h b/CORE/HDD/inc/wlan_hdd_tsf.h
index d9ba92cc9662..42d512983466 100644
--- a/CORE/HDD/inc/wlan_hdd_tsf.h
+++ b/CORE/HDD/inc/wlan_hdd_tsf.h
@@ -69,7 +69,6 @@ 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
@@ -82,7 +81,6 @@ 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
@@ -115,4 +113,61 @@ hdd_capture_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
}
#endif
+#if defined(WLAN_FEATURE_TSF_PLUS) && defined(WLAN_FEATURE_TSF)
+
+/**
+ * hdd_start_tsf_sync() - start tsf sync
+ * @adapter: pointer to adapter
+ *
+ * This function initialize and start TSF synchronization
+ *
+ * Return: Describe the execute result of this routine
+ */
+int hdd_start_tsf_sync(hdd_adapter_t *adapter);
+
+/**
+ * hdd_stop_tsf_sync() - stop tsf sync
+ * @adapter: pointer to adapter
+ *
+ * This function stop and de-initialize TSF synchronization
+ *
+ * Return: Describe the execute result of this routine
+ */
+int hdd_stop_tsf_sync(hdd_adapter_t *adapter);
+
+/**
+ * hdd_tsf_notify_wlan_state_change() -
+ * notify tsf module of wlan connection state
+ * @old_state: old wlan state
+ * @new_state: new wlan state
+ *
+ * This function check the old and new connection state, determine whether
+ * to start or stop tsf sync
+ *
+ * Return: nothing
+ */
+void hdd_tsf_notify_wlan_state_change(hdd_adapter_t *adapter,
+ eConnectionState old_state,
+ eConnectionState new_state);
+
+#else
+static inline int hdd_start_tsf_sync(hdd_adapter_t *adapter)
+{
+ return -ENOTSUPP;
+}
+
+static inline int hdd_stop_tsf_sync(hdd_adapter_t *adapter)
+{
+ return -ENOTSUPP;
+}
+
+static inline
+void hdd_tsf_notify_wlan_state_change(hdd_adapter_t *adapter,
+ eConnectionState old_state,
+ eConnectionState new_state)
+
+{
+}
+#endif
+
#endif
diff --git a/CORE/HDD/inc/wlan_hdd_wext.h b/CORE/HDD/inc/wlan_hdd_wext.h
index dac20cc0f39b..6a47ede7e6e7 100644
--- a/CORE/HDD/inc/wlan_hdd_wext.h
+++ b/CORE/HDD/inc/wlan_hdd_wext.h
@@ -258,6 +258,7 @@ typedef enum
* 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
+ * TSF_DISABLED_BY_TSFPLUS: cap_tsf/get_tsf are disabled due to TSF_PLUS
*/
enum hdd_tsf_get_state {
TSF_RETURN = 0,
@@ -268,7 +269,8 @@ enum hdd_tsf_get_state {
TSF_GET_FAIL,
TSF_RESET_GPIO_FAIL,
TSF_SAP_NOT_STARTED_NO_TSF,
- TSF_NOT_READY
+ TSF_NOT_READY,
+ TSF_DISABLED_BY_TSFPLUS
};
/**
diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c
index 7c632ec814ef..83b0b80add19 100644
--- a/CORE/HDD/src/wlan_hdd_assoc.c
+++ b/CORE/HDD/src/wlan_hdd_assoc.c
@@ -71,6 +71,8 @@
#include <wlan_logging_sock_svc.h>
#include "tl_shim.h"
#include "wlan_hdd_oemdata.h"
+#include "wlan_hdd_tsf.h"
+
#include "adf_trace.h"
struct ether_addr
@@ -156,6 +158,9 @@ v_VOID_t hdd_connSetConnectionState( hdd_adapter_t *pAdapter,
hddLog(LOG1, FL("%pS Changed connectionState from oldState:%d to State:%d"),
(void *)_RET_IP_,
pHddStaCtx->conn_info.connState, connState);
+
+ hdd_tsf_notify_wlan_state_change(pAdapter,
+ pHddStaCtx->conn_info.connState, connState);
pHddStaCtx->conn_info.connState = connState;
/* Check is pending ROC request or not when connection state changed */
diff --git a/CORE/HDD/src/wlan_hdd_tsf.c b/CORE/HDD/src/wlan_hdd_tsf.c
index f328a4450144..5a73407e2c0d 100644
--- a/CORE/HDD/src/wlan_hdd_tsf.c
+++ b/CORE/HDD/src/wlan_hdd_tsf.c
@@ -44,6 +44,26 @@ enum hdd_tsf_op_result {
HDD_TSF_OP_FAIL
};
+#ifdef WLAN_FEATURE_TSF_PLUS
+static inline void hdd_set_th_sync_status(hdd_adapter_t *adapter,
+ bool initialized)
+{
+ adf_os_atomic_set(&adapter->tsf_sync_ready_flag,
+ (initialized ? 1 : 0));
+}
+
+static inline bool hdd_get_th_sync_status(hdd_adapter_t *adapter)
+{
+ return (!adf_os_atomic_read(&adapter->tsf_sync_ready_flag) == 0);
+}
+
+#else
+static inline bool hdd_get_th_sync_status(hdd_adapter_t *adapter)
+{
+ return true;
+}
+#endif
+
static
enum hdd_tsf_get_state hdd_tsf_check_conn_state(hdd_adapter_t *adapter)
{
@@ -87,7 +107,8 @@ static bool hdd_tsf_is_initialized(hdd_adapter_t *adapter)
return false;
}
- if (!adf_os_atomic_read(&hddctx->tsf_ready_flag)) {
+ if (!adf_os_atomic_read(&hddctx->tsf_ready_flag) ||
+ !hdd_get_th_sync_status(adapter)) {
hddLog(VOS_TRACE_LEVEL_ERROR,
FL("TSF is not initialized"));
return false;
@@ -165,6 +186,7 @@ static enum hdd_tsf_op_result hdd_capture_tsf_internal(
}
hddLog(VOS_TRACE_LEVEL_INFO,
FL("-ioctl return cap tsf cmd"));
+
return HDD_TSF_OP_SUCC;
}
@@ -236,18 +258,522 @@ static enum hdd_tsf_op_result hdd_indicate_tsf_internal(
}
}
-int hdd_capture_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
+#ifdef WLAN_FEATURE_TSF_PLUS
+/* unit for target time: us; host time: ns */
+#define HOST_TO_TARGET_TIME_RATIO NSEC_PER_USEC
+#define MAX_ALLOWED_DEVIATION_NS (20 * NSEC_PER_MSEC)
+#define MAX_CONTINUOUS_ERROR_CNT 3
+#define WLAN_HDD_CAPTURE_TSF_INTERVAL_SEC 500
+#define WLAN_HDD_CAPTURE_TSF_INIT_INTERVAL_MS 100
+
+/**
+ * TS_STATUS - timestamp status
+ *
+ * HDD_TS_STATUS_WAITING: one of the stamp-pair
+ * is not updated
+ * HDD_TS_STATUS_READY: valid tstamp-pair
+ * HDD_TS_STATUS_INVALID: invalid tstamp-pair
+ */
+enum hdd_ts_status {
+ HDD_TS_STATUS_WAITING,
+ HDD_TS_STATUS_READY,
+ HDD_TS_STATUS_INVALID
+};
+
+static
+enum hdd_tsf_op_result __hdd_start_tsf_sync(hdd_adapter_t *adapter)
{
- return (hdd_capture_tsf_internal(adapter, buf, len) ==
+ VOS_STATUS ret;
+
+ if (!hdd_get_th_sync_status(adapter)) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("Host Target sync has not initialized"));
+ return HDD_TSF_OP_FAIL;
+ }
+
+ ret = vos_timer_start(&adapter->host_target_sync_timer,
+ WLAN_HDD_CAPTURE_TSF_INIT_INTERVAL_MS);
+ if (ret != VOS_STATUS_SUCCESS && ret != VOS_STATUS_E_ALREADY) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("Failed to start timer, ret: %d"), ret);
+ return HDD_TSF_OP_FAIL;
+ }
+ return HDD_TSF_OP_SUCC;
+}
+
+static
+enum hdd_tsf_op_result __hdd_stop_tsf_sync(hdd_adapter_t *adapter)
+{
+ VOS_STATUS ret;
+
+ if (!hdd_get_th_sync_status(adapter)) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("Host Target sync has not initialized"));
+ return HDD_TSF_OP_SUCC;
+ }
+
+ ret = vos_timer_stop(&adapter->host_target_sync_timer);
+ if (ret != VOS_STATUS_SUCCESS) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("Failed to stop timer, ret: %d"), ret);
+ return HDD_TSF_OP_FAIL;
+ }
+ return HDD_TSF_OP_SUCC;
+}
+
+static inline void hdd_reset_timestamps(hdd_adapter_t *adapter)
+{
+ spin_lock_bh(&adapter->host_target_sync_lock);
+ adapter->cur_host_time = 0;
+ adapter->cur_target_time = 0;
+ adapter->last_host_time = 0;
+ adapter->last_target_time = 0;
+ spin_unlock_bh(&adapter->host_target_sync_lock);
+}
+
+/**
+ * hdd_check_timestamp_status() - return the tstamp status
+ *
+ * @last_target_time: the last saved target time
+ * @last_host_time: the last saved host time
+ * @cur_target_time : new target time
+ * @cur_host_time : new host time
+ *
+ * This function check the new timstamp-pair(cur_host_time/cur_target_time)
+ *
+ * Return:
+ * HDD_TS_STATUS_WAITING: cur_host_time or cur_host_time is 0
+ * HDD_TS_STATUS_READY: cur_target_time/cur_host_time is a valid pair,
+ * and can be saved
+ * HDD_TS_STATUS_INVALID: cur_target_time/cur_host_time is a invalid pair,
+ * should be discard
+ */
+static
+enum hdd_ts_status hdd_check_timestamp_status(
+ uint64_t last_target_time,
+ uint64_t last_host_time,
+ uint64_t cur_target_time,
+ uint64_t cur_host_time)
+{
+ uint64_t delta_ns, delta_target_time, delta_host_time;
+
+ /* one or more are not updated, need to wait */
+ if (cur_target_time == 0 || cur_host_time == 0)
+ return HDD_TS_STATUS_WAITING;
+
+ /* init value, it's the first time to update the pair */
+ if (last_target_time == 0 && last_host_time == 0)
+ return HDD_TS_STATUS_READY;
+
+ /* the new values should be greater than the saved values */
+ if ((cur_target_time <= last_target_time) ||
+ (cur_host_time <= last_host_time)) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("Invalid timestamps!last_target_time: %llu;"
+ "last_host_time: %llu; cur_target_time: %llu;"
+ "cur_host_time: %llu"),
+ last_target_time, last_host_time,
+ cur_target_time, cur_host_time);
+ return HDD_TS_STATUS_INVALID;
+ }
+
+ delta_target_time = (cur_target_time - last_target_time) *
+ HOST_TO_TARGET_TIME_RATIO;
+ delta_host_time = cur_host_time - last_host_time;
+
+ /*
+ * DO NOT use abs64() , a big uint64 value might be turned to
+ * a small int64 value
+ */
+ delta_ns = ((delta_target_time > delta_host_time) ?
+ (delta_target_time - delta_host_time) :
+ (delta_host_time - delta_target_time));
+
+ /* the deviation should be smaller than a threshold */
+ if (delta_ns > MAX_ALLOWED_DEVIATION_NS) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("Invalid timestamps - delta: %llu ns"), delta_ns);
+ return HDD_TS_STATUS_INVALID;
+ }
+ return HDD_TS_STATUS_READY;
+}
+
+static void hdd_update_timestamp(hdd_adapter_t *adapter,
+ uint64_t target_time, uint64_t host_time)
+{
+ int interval = 0;
+ enum hdd_ts_status sync_status;
+
+ if (!adapter)
+ return;
+
+ spin_lock_bh(&adapter->host_target_sync_lock);
+ if (target_time > 0)
+ adapter->cur_target_time = target_time;
+ if (host_time > 0)
+ adapter->cur_host_time = host_time;
+
+ sync_status = hdd_check_timestamp_status(adapter->last_target_time,
+ adapter->last_host_time,
+ adapter->cur_target_time,
+ adapter->cur_host_time);
+ switch (sync_status) {
+ case HDD_TS_STATUS_INVALID:
+ if (++adapter->continuous_error_count <
+ MAX_CONTINUOUS_ERROR_CNT) {
+ interval =
+ WLAN_HDD_CAPTURE_TSF_INIT_INTERVAL_MS;
+ adapter->cur_target_time = 0;
+ adapter->cur_host_time = 0;
+ break;
+ }
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ FL("Reach the max continuous error count"));
+ /*
+ * fall through:
+ * If reach MAX_CONTINUOUS_ERROR_CNT, treat it as a
+ * valid pair
+ */
+ case HDD_TS_STATUS_READY:
+ adapter->last_target_time = adapter->cur_target_time;
+ adapter->last_host_time = adapter->cur_host_time;
+ adapter->cur_target_time = 0;
+ adapter->cur_host_time = 0;
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ FL("ts-pair updated: target: %llu; host: %llu"),
+ adapter->last_target_time,
+ adapter->last_host_time);
+ interval = WLAN_HDD_CAPTURE_TSF_INTERVAL_SEC *
+ MSEC_PER_SEC;
+ adapter->continuous_error_count = 0;
+ break;
+ case HDD_TS_STATUS_WAITING:
+ interval = 0;
+ break;
+ }
+ spin_unlock_bh(&adapter->host_target_sync_lock);
+
+ if (interval > 0)
+ vos_timer_start(&adapter->host_target_sync_timer, interval);
+}
+
+static inline uint64_t hdd_get_monotonic_host_time(void)
+{
+ struct timespec ts;
+
+ getrawmonotonic(&ts);
+ return timespec_to_ns(&ts);
+}
+
+static void hdd_capture_tsf_timer_expired_handler(void *arg)
+{
+ uint32_t tsf_op_resp;
+ hdd_adapter_t *adapter;
+
+ if (!arg)
+ return;
+
+ adapter = (hdd_adapter_t *)arg;
+ hdd_capture_tsf_internal(adapter, &tsf_op_resp, 1);
+}
+
+static irqreturn_t hdd_tsf_captured_irq_handler(int irq, void *arg)
+{
+ hdd_adapter_t *adapter;
+ hdd_context_t *hdd_ctx;
+ uint64_t host_time;
+ char *name = NULL;
+
+ if (!arg)
+ return IRQ_NONE;
+
+ host_time = hdd_get_monotonic_host_time();
+
+ hdd_ctx = (hdd_context_t *)arg;
+
+ adapter = hdd_ctx->cap_tsf_context;
+ if (!adapter)
+ return IRQ_HANDLED;
+
+ if (!hdd_tsf_is_initialized(adapter)) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("tsf is not init, ignore irq"));
+ return IRQ_HANDLED;
+ }
+
+ hdd_update_timestamp(adapter, 0, host_time);
+ if (adapter->dev)
+ name = adapter->dev->name;
+
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ FL("irq: %d - iface: %s - host_time: %llu"),
+ irq, (!name ? "none" : name), host_time);
+
+ return IRQ_HANDLED;
+}
+
+static enum hdd_tsf_op_result hdd_tsf_sync_init(hdd_adapter_t *adapter)
+{
+ VOS_STATUS ret;
+ hdd_context_t *hddctx;
+
+ if (!adapter)
+ 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 (!adf_os_atomic_read(&hddctx->tsf_ready_flag)) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("TSF feature has NOT been initialized"));
+ return HDD_TSF_OP_FAIL;
+ }
+
+ if (hdd_get_th_sync_status(adapter)) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("Host Target sync has been initialized!!"));
+ return HDD_TSF_OP_SUCC;
+ }
+
+ spin_lock_init(&adapter->host_target_sync_lock);
+
+ hdd_reset_timestamps(adapter);
+
+ ret = vos_timer_init(&adapter->host_target_sync_timer,
+ VOS_TIMER_TYPE_SW,
+ hdd_capture_tsf_timer_expired_handler,
+ (void *)adapter);
+ if (ret != VOS_STATUS_SUCCESS) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("Failed to init timer, ret: %d"), ret);
+ goto fail;
+ }
+
+ hdd_set_th_sync_status(adapter, true);
+
+ return HDD_TSF_OP_SUCC;
+fail:
+ hdd_set_th_sync_status(adapter, false);
+ return HDD_TSF_OP_FAIL;
+}
+
+static enum hdd_tsf_op_result hdd_tsf_sync_deinit(hdd_adapter_t *adapter)
+{
+ VOS_STATUS ret;
+ hdd_context_t *hddctx;
+
+ if (!adapter)
+ return HDD_TSF_OP_FAIL;
+
+ if (!hdd_get_th_sync_status(adapter)) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("Host Target sync has not been initialized!!"));
+ return HDD_TSF_OP_SUCC;
+ }
+
+ hdd_set_th_sync_status(adapter, false);
+
+ ret = vos_timer_destroy(&adapter->host_target_sync_timer);
+ if (ret != VOS_STATUS_SUCCESS)
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("Failed to destroy timer, ret: %d"), ret);
+
+ hddctx = WLAN_HDD_GET_CTX(adapter);
+
+ /* reset the cap_tsf flag and gpio if needed */
+ if (hddctx && adf_os_atomic_read(&hddctx->cap_tsf_flag) &&
+ hddctx->cap_tsf_context == adapter) {
+ int reset_ret = hdd_reset_tsf_gpio(adapter);
+
+ if (reset_ret)
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("Failed to reset tsf gpio, ret:%d"),
+ reset_ret);
+ hddctx->cap_tsf_context = NULL;
+ adf_os_atomic_set(&hddctx->cap_tsf_flag, 0);
+ }
+
+ hdd_reset_timestamps(adapter);
+ return HDD_TSF_OP_SUCC;
+}
+
+static inline void hdd_update_tsf(hdd_adapter_t *adapter, uint64_t tsf)
+{
+ uint32_t tsf_op_resp[3];
+
+ hdd_indicate_tsf_internal(adapter, tsf_op_resp, 3);
+ hdd_update_timestamp(adapter, tsf, 0);
+}
+
+int hdd_start_tsf_sync(hdd_adapter_t *adapter)
+{
+ enum hdd_tsf_op_result ret;
+
+ if (!adapter)
+ return -EINVAL;
+
+ ret = hdd_tsf_sync_init(adapter);
+ if (ret != HDD_TSF_OP_SUCC) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("Failed to init tsf sync, ret: %d"), ret);
+ return -EINVAL;
+ }
+
+ return (__hdd_start_tsf_sync(adapter) ==
HDD_TSF_OP_SUCC ? 0 : -EINVAL);
}
-int hdd_indicate_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
+int hdd_stop_tsf_sync(hdd_adapter_t *adapter)
+{
+ enum hdd_tsf_op_result ret;
+
+ if (!adapter)
+ return -EINVAL;
+
+ ret = __hdd_stop_tsf_sync(adapter);
+ if (ret != HDD_TSF_OP_SUCC)
+ return -EINVAL;
+
+ ret = hdd_tsf_sync_deinit(adapter);
+ if (ret != HDD_TSF_OP_SUCC) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("Failed to deinit tsf sync, ret: %d"), ret);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static inline int __hdd_capture_tsf(hdd_adapter_t *adapter,
+ uint32_t *buf, int len)
+{
+ if (!adapter || !buf) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("invalid pointer"));
+ return -EINVAL;
+ }
+
+ if (len != 1)
+ return -EINVAL;
+
+ buf[0] = TSF_DISABLED_BY_TSFPLUS;
+
+ return 0;
+}
+
+static inline int __hdd_indicate_tsf(hdd_adapter_t *adapter,
+ uint32_t *buf, int len)
+{
+ if (!adapter || !buf) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("invalid pointer"));
+ return -EINVAL;
+ }
+
+ if (len != 3)
+ return -EINVAL;
+
+ buf[0] = TSF_DISABLED_BY_TSFPLUS;
+ buf[1] = 0;
+ buf[2] = 0;
+
+ return 0;
+}
+
+static inline
+enum hdd_tsf_op_result wlan_hdd_tsf_plus_init(hdd_context_t *hdd_ctx)
+{
+ int ret;
+
+ ret = cnss_common_register_tsf_captured_handler(
+ hdd_ctx->parent_dev,
+ hdd_tsf_captured_irq_handler,
+ (void *)hdd_ctx);
+ if (ret != 0) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("Failed to register irq handler: %d"), ret);
+ return HDD_TSF_OP_FAIL;
+ }
+ return HDD_TSF_OP_SUCC;
+}
+
+static inline
+enum hdd_tsf_op_result wlan_hdd_tsf_plus_deinit(hdd_context_t *hdd_ctx)
+{
+ int ret;
+
+ ret = cnss_common_unregister_tsf_captured_handler(
+ hdd_ctx->parent_dev,
+ (void *)hdd_ctx);
+ if (ret != 0) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("Failed to unregister irq handler, ret:%d"),
+ ret);
+ ret = HDD_TSF_OP_FAIL;
+ }
+
+ return HDD_TSF_OP_SUCC;
+}
+
+void hdd_tsf_notify_wlan_state_change(hdd_adapter_t *adapter,
+ eConnectionState old_state,
+ eConnectionState new_state)
+{
+ if (!adapter)
+ return;
+
+ if (old_state != eConnectionState_Associated &&
+ new_state == eConnectionState_Associated)
+ hdd_start_tsf_sync(adapter);
+ else if (old_state == eConnectionState_Associated &&
+ new_state != eConnectionState_Associated)
+ hdd_stop_tsf_sync(adapter);
+}
+#else
+static inline void hdd_update_tsf(hdd_adapter_t *adapter, uint64_t tsf)
+{
+}
+
+static inline 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);
}
+static inline 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);
+}
+
+static inline
+enum hdd_tsf_op_result wlan_hdd_tsf_plus_init(hdd_context_t *hdd_ctx)
+{
+ return HDD_TSF_OP_SUCC;
+}
+
+static inline
+enum hdd_tsf_op_result wlan_hdd_tsf_plus_deinit(hdd_context_t *hdd_ctx)
+{
+ return HDD_TSF_OP_SUCC;
+}
+#endif /* WLAN_FEATURE_TSF_PLUS */
+
+int hdd_capture_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
+{
+ return __hdd_capture_tsf(adapter, buf, len);
+}
+
+int hdd_indicate_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
+{
+ return __hdd_indicate_tsf(adapter, buf, len);
+}
+
/**
* hdd_get_tsf_cb() - handle tsf callback
*
@@ -299,6 +825,8 @@ static int hdd_get_tsf_cb(void *pcb_cxt, struct stsf *ptsf)
adapter->cur_target_time = ((uint64_t)ptsf->tsf_high << 32 |
ptsf->tsf_low);
+ hdd_update_tsf(adapter, adapter->cur_target_time);
+
hddLog(VOS_TRACE_LEVEL_INFO,
FL("hdd_get_tsf_cb sta=%u, tsf_low=%u, tsf_high=%u"),
ptsf->vdev_id, ptsf->tsf_low, ptsf->tsf_high);
@@ -335,6 +863,9 @@ void wlan_hdd_tsf_init(hdd_context_t *hdd_ctx)
goto fail;
}
+ if (wlan_hdd_tsf_plus_init(hdd_ctx) != HDD_TSF_OP_SUCC)
+ goto fail;
+
return;
fail:
@@ -358,6 +889,7 @@ void wlan_hdd_tsf_deinit(hdd_context_t *hdd_ctx)
hal_status);
}
+ wlan_hdd_tsf_plus_deinit(hdd_ctx);
adf_os_atomic_set(&hdd_ctx->tsf_ready_flag, 0);
adf_os_atomic_set(&hdd_ctx->cap_tsf_flag, 0);
}
diff --git a/Kbuild b/Kbuild
index ae5e617d044e..4d9549e251cb 100644
--- a/Kbuild
+++ b/Kbuild
@@ -48,6 +48,12 @@ ifeq ($(KERNEL_BUILD), 0)
CONFIG_MOBILE_ROUTER := y
endif
+ ifeq ($(CONFIG_ARCH_MSM8917), y)
+ ifeq ($(CONFIG_ROME_IF), sdio)
+ CONFIG_WLAN_SYNC_TSF_PLUS := y
+ endif
+ endif
+
# As per target team, build is done as follows:
# Defconfig : build with default flags
# Slub : defconfig + CONFIG_SLUB_DEBUG=y +
@@ -449,6 +455,10 @@ ifeq ($(CONFIG_QCOM_TDLS),y)
HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_tdls.o
endif
+ifeq ($(CONFIG_WLAN_SYNC_TSF_PLUS), y)
+CONFIG_WLAN_SYNC_TSF := y
+endif
+
ifeq ($(CONFIG_WLAN_SYNC_TSF),y)
HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_tsf.o
endif
@@ -1553,6 +1563,10 @@ ifeq ($(CONFIG_WLAN_SYNC_TSF),y)
CDEFINES += -DWLAN_FEATURE_TSF
endif
+ifeq ($(CONFIG_WLAN_SYNC_TSF_PLUS), y)
+CDEFINES += -DWLAN_FEATURE_TSF_PLUS
+endif
+
# Enable target dump for non-qualcomm platform
ifeq ($(CONFIG_NON_QC_PLATFORM), y)
CDEFINES += -DCONFIG_NON_QC_PLATFORM