prima: Add support for capture TSF request

Add new ioctls for supporting capture and get tsf value from FW

Change-Id: If7df81f75c5939cdd827e95cd53582aee5be46c9
CRs-fixed: 1112993
diff --git a/CORE/HDD/inc/qc_sap_ioctl.h b/CORE/HDD/inc/qc_sap_ioctl.h
index 303376b..764384e 100644
--- a/CORE/HDD/inc/qc_sap_ioctl.h
+++ b/CORE/HDD/inc/qc_sap_ioctl.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.
  *
@@ -177,6 +177,9 @@
 #define QCSAP_IOCTL_SET_TRAFFIC_MONITOR (SIOCIWFIRSTPRIV+24)
 #define QCSAP_IOCTL_AP_STATS            (SIOCIWFIRSTPRIV+25) // get routines should be odd numbered
 
+#define QCSAP_IOCTL_PRIV_SET_NONE_GET_THREE_INT  (SIOCIWFIRSTPRIV+27)
+#define QCSAP_IOCTL_GET_TSF 1
+
 #define MAX_VAR_ARGS         7
 #define QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED (SIOCIWFIRSTPRIV + 31)
 
@@ -191,7 +194,8 @@
     QCSAP_PARAM_SET_AUTO_CHANNEL = 11,
     QCSAP_PARAM_GET_FRAME_LOGS = 12,
     QCSAP_PARAM_SET_PROXIMITY = 13,
-    QCSAP_PARAM_SET_WOWL = 14
+    QCSAP_PARAM_SET_WOWL = 14,
+    QCSAP_PARAM_CAP_TSF = 15
 };
 
 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 1622631..4d9faa1 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -817,6 +817,64 @@
 } hdd_mdns_state_t;
 #endif /* MDNS_OFFLOAD */
 
+#ifdef WLAN_FEATURE_TSF
+
+#define HDD_TSF_CAP_REQ_TIMEOUT 2000
+#define HDD_TSF_GET_REQ_TIMEOUT 2000
+
+/**
+ * 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
+};
+
+/**
+ * struct hdd_tsf_ctx_s - TSF capture ctx
+ * @tsf_get_state : tsf action enum
+ * @tsf_capture_state: tsf capture state enum
+ * @tsf_capture_done_event : Indicate tsf completion
+ * @tsf_high : Higher 32-bit for 64-bit tsf
+ * @tsf_lo : Lower 32-bit for 64-bit tsf
+ *
+ */
+struct hdd_tsf_ctx_s {
+    enum hdd_tsf_get_state tsf_get_state;
+    enum hdd_tsf_capture_state tsf_capture_state;
+    vos_event_t tsf_capture_done_event;
+    vos_spin_lock_t tsf_lock;
+    uint32_t tsf_high;
+    uint32_t tsf_low;
+};
+
+#endif /* WLAN_FEATURE_TSF */
 /*
  * Per station structure kept in HDD for multiple station support for SoftAP
 */
@@ -1261,6 +1319,10 @@
 #ifdef MDNS_OFFLOAD
     hdd_mdns_state_t mdns_status;
 #endif /* MDNS_OFFLOAD */
+
+#ifdef WLAN_FEATURE_TSF
+    struct hdd_tsf_ctx_s tsf_cap_ctx;
+#endif
 };
 
 #define WLAN_HDD_GET_STATION_CTX_PTR(pAdapter) (&(pAdapter)->sessionCtx.station)
@@ -2047,4 +2109,27 @@
 
 void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter);
 
+#ifdef WLAN_FEATURE_TSF
+void wlan_hdd_tsf_init(hdd_adapter_t *adapter);
+int hdd_capture_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len);
+int hdd_indicate_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len);
+#else
+static inline void
+wlan_hdd_tsf_init(hdd_adapter_t *adapter)
+{
+	return;
+}
+
+static inline int
+hdd_indicate_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
+{
+	return -ENOTSUPP;
+}
+
+static inline int
+hdd_capture_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
+{
+	return -ENOTSUPP;
+}
+#endif
 #endif    // end #if !defined( WLAN_HDD_MAIN_H )
diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c
index 03e1871..5e6d326 100644
--- a/CORE/HDD/src/wlan_hdd_hostapd.c
+++ b/CORE/HDD/src/wlan_hdd_hostapd.c
@@ -2138,6 +2138,12 @@
                 }
                 break;
             }
+        case QCSAP_PARAM_CAP_TSF:
+            {
+                ret = hdd_capture_tsf(pHostapdAdapter,
+                                     (uint32_t *)&set_value, 1);
+                break;
+            }
         default:
             hddLog(LOGE, FL("Invalid setparam command %d value %d"),
                     sub_cmd, set_value);
@@ -3244,6 +3250,60 @@
     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 */
+
+    hdd_adapter_t *padapter = WLAN_HDD_GET_PRIV_PTR(dev);
+
+    switch (sub_cmd) {
+    case QCSAP_IOCTL_GET_TSF:
+        ret = hdd_indicate_tsf(padapter, value, 3);
+        break;
+    default:
+        hddLog(LOGE, FL("Invalid getparam command %d"), sub_cmd);
+        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;
+
+    vos_ssr_protect(__func__);
+    ret = __iw_softap_get_three(dev, info, wrqu, extra);
+    vos_ssr_unprotect(__func__);
+
+    return ret;
+}
 static int __iw_softap_set_channel_range(struct net_device *dev,
                                        struct iw_request_info *info,
                                        union iwreq_data *wrqu, char *extra)
@@ -4702,6 +4762,8 @@
       IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,  "setMcRate" },
   { QCSAP_PARAM_SET_PROXIMITY,
       IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,  "setProximity" },
+  { QCSAP_PARAM_CAP_TSF,
+     IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,  "cap_tsf" },
   { QCSAP_PARAM_SET_WOWL,
       IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0,  "wowl" },
   { QCSAP_IOCTL_GETPARAM,
@@ -4737,6 +4799,14 @@
         IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 6 , 0, "disassoc_sta" },
   { QCSAP_IOCTL_AP_STATS, 0,
         IW_PRIV_TYPE_CHAR | QCSAP_MAX_WSC_IE, "ap_stats" },
+  /* handlers for main ioctl */
+  { QCSAP_IOCTL_PRIV_SET_NONE_GET_THREE_INT, 0,
+       IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, "" },
+#ifdef WLAN_FEATURE_TSF
+  { QCSAP_IOCTL_GET_TSF, 0,
+       IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
+       "get_tsf" },
+#endif
   { QCSAP_IOCTL_GET_STATS, 0,
         IW_PRIV_TYPE_CHAR | QCSAP_MAX_STR_LEN, "getStats"},
   { QCSAP_IOCTL_CLR_STATS, 0, 0, "clearStats" },
@@ -4846,6 +4916,7 @@
    [QCSAP_IOCTL_ASSOC_STA_MACADDR - SIOCIWFIRSTPRIV] = iw_softap_getassoc_stamacaddr,
    [QCSAP_IOCTL_DISASSOC_STA - SIOCIWFIRSTPRIV] = iw_softap_disassoc_sta,
    [QCSAP_IOCTL_AP_STATS - SIOCIWFIRSTPRIV] = iw_softap_ap_stats,
+   [QCSAP_IOCTL_PRIV_SET_NONE_GET_THREE_INT - SIOCIWFIRSTPRIV] = iw_softap_get_three,
    [QCSAP_IOCTL_PRIV_SET_THREE_INT_GET_NONE - SIOCIWFIRSTPRIV]  = iw_set_three_ints_getnone,
    [QCSAP_IOCTL_PRIV_SET_VAR_INT_GET_NONE - SIOCIWFIRSTPRIV]     = iw_set_var_ints_getnone,
    [QCSAP_IOCTL_SET_CHANNEL_RANGE - SIOCIWFIRSTPRIV] = iw_softap_set_channel_range,
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index 4ba77a2..8ffb9fb 100644
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -8834,6 +8834,8 @@
           hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
           goto err_free_netdev;
       }
+      //Initialize the TSF capture data
+      wlan_hdd_tsf_init(pAdapter);
    }
    return pAdapter;
 
@@ -16324,6 +16326,8 @@
            "%s: enable mDNS offload successfully!", __func__);
     return TRUE;
 }
+
+
 #endif /* MDNS_OFFLOAD */
 
 /**
@@ -16389,6 +16393,314 @@
 	return;
 }
 
+#ifdef WLAN_FEATURE_TSF
+
+/**
+ * hdd_tsf_cb() - handle tsf request callback
+ *
+ * @pcb_cxt: pointer to the hdd_contex
+ * @ptsf: pointer to struct stsf
+ *
+ * Based on the request sent .
+ *
+ * Return: Describe the execute result of this routine
+ */
+static int hdd_tsf_cb(void *pcb_ctx, struct stsf *ptsf)
+{
+    hdd_context_t *hddctx;
+    int status;
+    hdd_adapter_t* adapter = (hdd_adapter_t*)pcb_ctx;
+
+    if (pcb_ctx == NULL || ptsf == NULL) {
+        hddLog(VOS_TRACE_LEVEL_ERROR,
+               FL("HDD context is not valid"));
+        return -EINVAL;
+    }
+
+    hddctx = (hdd_context_t *)pcb_ctx;
+    status = wlan_hdd_validate_context(hddctx);
+    if (0 != status)
+        return -EINVAL;
+
+    if (NULL == adapter) {
+        hddLog(VOS_TRACE_LEVEL_ERROR,
+               FL("failed to find adapter"));
+        return -EINVAL;
+    }
+
+    hddLog(VOS_TRACE_LEVEL_INFO,
+           FL("tsf cb handle event, device_mode is %d"),
+           adapter->device_mode);
+
+    /* copy the return value to hdd_tsf_ctx in adapter*/
+    if (ptsf->tsf_req_status) {
+
+        vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
+        adapter->tsf_cap_ctx.tsf_get_state = TSF_NOT_RETURNED_BY_FW;
+        adapter->tsf_cap_ctx.tsf_capture_state  = TSF_IDLE;
+        vos_event_set (&adapter->tsf_cap_ctx.tsf_capture_done_event);
+        vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
+
+        hddLog(VOS_TRACE_LEVEL_ERROR, FL("tsf req failure :%d"),
+               ptsf->tsf_req_status);
+        return ptsf->tsf_req_status;
+    }
+    /* If this is a get request.Store the tsf values in adapter. */
+    if (!ptsf->set_tsf_req) {
+        vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
+        adapter->tsf_cap_ctx.tsf_low  = ptsf->tsf_low;
+        adapter->tsf_cap_ctx.tsf_high = ptsf->tsf_high;
+        adapter->tsf_cap_ctx.tsf_get_state = TSF_RETURN;
+        adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
+        vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
+
+        hddLog(VOS_TRACE_LEVEL_INFO,
+               FL("hdd_get_tsf_cb sta=%u, tsf_low=%u, tsf_high=%u"),
+                   adapter->sessionId, ptsf->tsf_low, ptsf->tsf_high);
+    }
+    else {
+        vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
+        adapter->tsf_cap_ctx.tsf_capture_state = TSF_CAP_STATE;
+        adapter->tsf_cap_ctx.tsf_get_state = TSF_CURRENT_IN_CAP_STATE;
+        vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
+    }
+    vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
+    vos_event_set (&adapter->tsf_cap_ctx.tsf_capture_done_event);
+    vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
+
+    /* free allocated mem */
+    vos_mem_free(ptsf);
+
+    return 0;
+}
+
+/**
+ * hdd_capture_tsf() - capture tsf
+ *
+ * @adapter: pointer to adapter
+ * @buf: pointer to upper layer 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)
+{
+    int ret = 0;
+    hdd_station_ctx_t *hdd_sta_ctx;
+    hdd_context_t *hdd_ctx;
+    tSirCapTsfParams cap_tsf_params;
+    VOS_STATUS status;
+
+    if (adapter == NULL || buf == NULL) {
+        hddLog(VOS_TRACE_LEVEL_ERROR,
+               FL("invalid pointer"));
+        return -EINVAL;
+    }
+    if (len != 1)
+        return -EINVAL;
+
+    hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+
+    if (wlan_hdd_validate_context(hdd_ctx)) {
+        hddLog(VOS_TRACE_LEVEL_ERROR,
+               FL("invalid hdd ctx"));
+        return -EINVAL;
+    }
+    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("failed to cap tsf, not connect with ap"));
+            buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF;
+            return ret;
+        }
+    }
+    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_INFO,
+                FL("Soft AP / P2p GO not beaconing"));
+         buf[0] = TSF_SAP_NOT_STARTED_NO_TSF;
+         return ret;
+    }
+    if (adapter->tsf_cap_ctx.tsf_capture_state == TSF_CAP_STATE) {
+        hddLog(VOS_TRACE_LEVEL_INFO,
+               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;
+        cap_tsf_params.session_id = adapter->sessionId;
+        cap_tsf_params.tsf_rsp_cb_func = hdd_tsf_cb;
+        cap_tsf_params.tsf_rsp_cb_ctx = adapter;
+
+        vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
+        adapter->tsf_cap_ctx.tsf_capture_state = TSF_CAP_STATE;
+        adapter->tsf_cap_ctx.tsf_get_state = TSF_CURRENT_IN_CAP_STATE;
+        vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
+
+        ret = sme_capture_tsf_req(hdd_ctx->hHal, cap_tsf_params);
+
+        if (ret != VOS_STATUS_SUCCESS) {
+            hddLog(VOS_TRACE_LEVEL_ERROR, FL("capture fail"));
+            buf[0] = TSF_CAPTURE_FAIL;
+            vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
+            adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
+            vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
+            return -EINVAL;
+        }
+        /* wait till we get a response from fw */
+        status = vos_wait_single_event(&adapter->tsf_cap_ctx.
+                                       tsf_capture_done_event,
+                                       HDD_TSF_CAP_REQ_TIMEOUT);
+
+        if (!VOS_IS_STATUS_SUCCESS(status)) {
+             VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                       ("capture tsf vos wait for single_event failed!! %d"),
+                       adapter->tsf_cap_ctx.tsf_get_state);
+
+              vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
+              adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
+              vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
+
+             return -EINVAL;
+        }
+    }
+    buf[0] = TSF_RETURN;
+    hddLog(VOS_TRACE_LEVEL_INFO,
+           FL("ioctl return cap tsf cmd, ret = %d"), ret);
+    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 uplayer.
+ *
+ * Return: Describe the execute result of this routine
+ */
+int hdd_indicate_tsf(hdd_adapter_t *adapter, uint32_t *buf, int len)
+{
+    int ret = 0;
+    hdd_station_ctx_t *hdd_sta_ctx;
+    hdd_context_t *hdd_ctx;
+    tSirCapTsfParams cap_tsf_params;
+    VOS_STATUS status;
+
+    if (adapter == NULL || buf == NULL) {
+        hddLog(VOS_TRACE_LEVEL_ERROR,
+               FL("invalid pointer"));
+        return -EINVAL;
+    }
+    if (len != 3)
+        return -EINVAL;
+
+    buf [1] = 0;
+    buf [2] = 0;
+    hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+
+    if (wlan_hdd_validate_context(hdd_ctx)) {
+        hddLog(VOS_TRACE_LEVEL_ERROR,
+               FL("invalid hdd ctx"));
+        return -EINVAL;
+    }
+    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("failed to cap tsf, not connect with ap"));
+            buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF;
+            return ret;
+        }
+    }
+    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_INFO,
+                FL("Soft AP / P2p GO not beaconing"));
+         buf[0] = TSF_SAP_NOT_STARTED_NO_TSF;
+         return ret;
+    }
+
+    if (adapter->tsf_cap_ctx.tsf_capture_state != TSF_CAP_STATE ||
+        adapter->tsf_cap_ctx.tsf_get_state != TSF_CURRENT_IN_CAP_STATE ) {
+        hddLog(VOS_TRACE_LEVEL_INFO,
+        FL("Not in capture state,Enter capture state first"));
+        buf[0] = TSF_GET_FAIL;
+    } else {
+        hddLog(VOS_TRACE_LEVEL_INFO, FL("ioctl issue cap tsf cmd"));
+        cap_tsf_params.session_id = adapter->sessionId;
+        cap_tsf_params.tsf_rsp_cb_func = hdd_tsf_cb;
+        cap_tsf_params.tsf_rsp_cb_ctx = adapter;
+
+        ret = sme_get_tsf_req(hdd_ctx->hHal, cap_tsf_params);
+
+        if (ret != VOS_STATUS_SUCCESS) {
+            hddLog(VOS_TRACE_LEVEL_ERROR, FL("capture fail"));
+            buf[0] = TSF_CAPTURE_FAIL;
+            vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
+            adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
+            vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
+            return -EINVAL;
+        }
+        /* wait till we get a response from fw */
+        status = vos_wait_single_event(&adapter->tsf_cap_ctx.
+                                        tsf_capture_done_event,
+                                        HDD_TSF_GET_REQ_TIMEOUT);
+
+        if (!VOS_IS_STATUS_SUCCESS(status)) {
+             VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                       ("capture tsf vos wait for single_event failed!! %d"),
+                       status);
+
+             vos_spin_lock_acquire(&adapter->tsf_cap_ctx.tsf_lock);
+             adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
+             vos_spin_lock_release(&adapter->tsf_cap_ctx.tsf_lock);
+             return status;
+        }
+        buf[1] = adapter->tsf_cap_ctx.tsf_low;
+        buf[2] = adapter->tsf_cap_ctx.tsf_high;
+
+        hddLog(VOS_TRACE_LEVEL_INFO,
+               FL("get tsf cmd,status=%u, tsf_low=%u, tsf_high=%u"),
+               buf[0], buf[1], buf[2]);
+    }
+    hddLog(VOS_TRACE_LEVEL_INFO,
+           FL("ioctl return cap tsf cmd, ret = %d"), ret);
+    return ret;
+}
+
+void wlan_hdd_tsf_init(hdd_adapter_t *adapter)
+{
+
+    if (adapter == NULL) {
+       hddLog(VOS_TRACE_LEVEL_ERROR,
+              FL("TSF init on a null adapter!"));
+       return;
+   }
+
+   adapter->tsf_cap_ctx.tsf_get_state = TSF_RETURN;
+   adapter->tsf_cap_ctx.tsf_capture_state = TSF_IDLE;
+   vos_event_init(&adapter->tsf_cap_ctx.tsf_capture_done_event);
+   vos_spin_lock_init(&adapter->tsf_cap_ctx.tsf_lock);
+   adapter->tsf_cap_ctx.tsf_high = 0;
+   adapter->tsf_cap_ctx.tsf_low = 0;
+}
+
+#endif
+
 //Register the module init/exit functions
 module_init(hdd_module_init);
 module_exit(hdd_module_exit);
diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c
index c3b9d40..2f6b9fd 100644
--- a/CORE/HDD/src/wlan_hdd_wext.c
+++ b/CORE/HDD/src/wlan_hdd_wext.c
@@ -174,6 +174,7 @@
 #define  WE_SET_MONITOR_STATE             22
 #define  WE_SET_PKT_STATS_ENABLE_DISABLE  23
 #define  WE_SET_PROXIMITY_ENABLE  24
+#define  WE_CAP_TSF    25
 
 /* Private ioctls and their sub-ioctls */
 #define WLAN_PRIV_SET_NONE_GET_INT    (SIOCIWFIRSTPRIV + 1)
@@ -295,7 +296,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
 
 #ifdef FEATURE_OEM_DATA_SUPPORT
 /* Private ioctls for setting the measurement configuration */
@@ -6330,6 +6332,14 @@
             ret = wlan_hdd_set_proximity(set_value, hHal);
             break;
         }
+        case WE_CAP_TSF:
+        {
+            if (NULL == hHal)
+                return -EINVAL;
+
+            ret = hdd_capture_tsf(pAdapter, (uint32_t *)&set_value, 1);
+            break;
+        }
         default:
         {
             hddLog(LOGE, "Invalid IOCTL setvalue command %d value %d",
@@ -8475,6 +8485,62 @@
    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 = 0; /* success */
+    uint32_t *value = (int *)extra;
+    hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+
+    hddLog(VOS_TRACE_LEVEL_INFO, FL("param = %d"), value[0]);
+
+    switch (value[0]) {
+    case WE_GET_TSF:
+        ret = hdd_indicate_tsf(adapter, value, 3);
+        break;
+    default:
+        hddLog(VOS_TRACE_LEVEL_ERROR,
+               FL("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;
+
+    vos_ssr_protect(__func__);
+    ret = __iw_setnone_get_threeint(dev, info, wrqu, extra);
+    vos_ssr_unprotect(__func__);
+
+    return ret;
+}
+
 #ifdef WLAN_FEATURE_VOWIFI_11R
 //
 //
@@ -10979,6 +11045,8 @@
    [WLAN_PRIV_ADD_TSPEC             - SIOCIWFIRSTPRIV]   = iw_add_tspec,
    [WLAN_PRIV_DEL_TSPEC             - SIOCIWFIRSTPRIV]   = iw_del_tspec,
    [WLAN_PRIV_GET_TSPEC             - SIOCIWFIRSTPRIV]   = iw_get_tspec,
+   [WLAN_PRIV_SET_NONE_GET_THREE_INT - SIOCIWFIRSTPRIV]  =
+                                       iw_setnone_get_threeint,
 #ifdef FEATURE_OEM_DATA_SUPPORT
    [WLAN_PRIV_SET_OEM_DATA_REQ - SIOCIWFIRSTPRIV] = iw_set_oem_data_req, //oem data req Specifc
    [WLAN_PRIV_GET_OEM_DATA_RSP - SIOCIWFIRSTPRIV] = iw_get_oem_data_rsp, //oem data req Specifc
@@ -11141,6 +11209,12 @@
     {   WE_SET_PROXIMITY_ENABLE,
         IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
         0, "setProximity" },
+
+#ifdef WLAN_FEATURE_TSF
+    {   WE_CAP_TSF,
+        IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+        0, "cap_tsf" },
+#endif
     /* handlers for main ioctl */
     {   WLAN_PRIV_SET_NONE_GET_INT,
         0,
@@ -11497,7 +11571,17 @@
         IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
         IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
         "getTspec" },
-
+    /* handlers for main ioctl */
+    {   WLAN_PRIV_SET_NONE_GET_THREE_INT,
+        0,
+        IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
+        "" },
+#ifdef WLAN_FEATURE_TSF
+    {   WE_GET_TSF,
+        0,
+        IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
+        "get_tsf" },
+#endif
 #ifdef FEATURE_OEM_DATA_SUPPORT
     /* handlers for main ioctl - OEM DATA */
     {
diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h
index 56ee96a..379e905 100644
--- a/CORE/MAC/inc/sirApi.h
+++ b/CORE/MAC/inc/sirApi.h
@@ -5837,7 +5837,7 @@
 typedef struct
 {
     tANI_U32 request_id;
-    tANI_U8 session_id;
+    tANI_U8  session_id;
     tANI_U32 lost_ssid_sample_size;
     tANI_U32 ssid_count;
     tSirSsidThresholdParam ssid[WLAN_EXTSCAN_MAX_HOTLIST_SSIDS];
@@ -6256,4 +6256,40 @@
 
 #endif /* SAP_AUTH_OFFLOAD */
 
+/**
+ * struct stsf - the basic stsf structure
+ *
+ * @session_id: session id from adapter
+ * @set_req: set/get request flag.
+ * @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 session_id;
+    bool     set_tsf_req;
+    uint32_t tsf_low;
+    uint32_t tsf_high;
+    bool tsf_req_status;
+};
+
+typedef int(*tsf_rsp_cb)(void *tsf_ctx, struct stsf *pTsf);
+
+/**
+ * struct tCapTsfParams - capture tsf request
+ * @bss_idx: bss index, SAP/STA
+ * @session_id: adapter session id
+ * @bssid: bssid for SAP/STA
+ * @tsf_rsp_cb_func : handler for tsf rsp from fw
+ * @tsf_rsp_cb_ctx : hdd ctx for tsf rsp handler
+ */
+typedef struct {
+    tANI_U8 bss_idx;
+    tANI_U8 session_id;
+    tSirMacAddr  bssid;
+    tsf_rsp_cb tsf_rsp_cb_func;
+    void * tsf_rsp_cb_ctx;
+}tSirCapTsfParams,*tpSirCapTsfParams;
+
 #endif /* __SIR_API_H */
diff --git a/CORE/MAC/inc/wniApi.h b/CORE/MAC/inc/wniApi.h
index ff69d7f..718af27 100644
--- a/CORE/MAC/inc/wniApi.h
+++ b/CORE/MAC/inc/wniApi.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2013, 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, 2016-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -387,6 +387,8 @@
     eWNI_SME_SET_TDLS_2040_BSSCOEX_REQ,
     eWNI_SME_DEL_ALL_TDLS_PEERS,
     eWNI_SME_REGISTER_MGMT_FRAME_CB,
+    eWNI_SME_CAP_TSF_REQ,
+    eWNI_SME_GET_TSF_REQ,
     eWNI_SME_MSG_TYPES_END
 };
 
diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h
index bac3ba8..a911c33 100644
--- a/CORE/MAC/src/include/sirParams.h
+++ b/CORE/MAC/src/include/sirParams.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.
  *
@@ -792,6 +792,9 @@
 #define SIR_HAL_AP_FIND_IND                (SIR_HAL_ITC_MSG_TYPES_BEGIN + 300)
 #endif/* WLAN_FEATURE_APFIND */
 
+#define SIR_HAL_CAP_TSF_REQ                (SIR_HAL_ITC_MSG_TYPES_BEGIN + 300)
+#define SIR_HAL_GET_TSF_REQ                (SIR_HAL_ITC_MSG_TYPES_BEGIN + 301)
+
 #define SIR_HAL_MSG_TYPES_END              (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF)
 
 // CFG message types
diff --git a/CORE/MAC/src/pe/lim/limApi.c b/CORE/MAC/src/pe/lim/limApi.c
index e2dd714..24a0fa4 100644
--- a/CORE/MAC/src/pe/lim/limApi.c
+++ b/CORE/MAC/src/pe/lim/limApi.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -2697,3 +2697,105 @@
     }
     return (status);
 }
+/**
+ * lim_process_sme_cap_tsf_req()- send cap tsf request to WDA
+ * Get bss_idx from PE and fill in cap tsf request.
+ * @pMac:Mac ctx
+ * @pMsgBuf: message buffer from sme
+ * Returns success on post to WDA, otherwise failure
+ */
+
+tSirRetStatus lim_process_sme_cap_tsf_req(tpAniSirGlobal pMac,
+                                          tANI_U32 *pMsgBuf)
+{
+    tSirCapTsfParams *pMsg = NULL;
+    tpPESession psessionEntry = NULL;
+    uint8_t sessionId;
+    tSirMsgQ               msg;
+    tSirCapTsfParams      *cap_tsf_params;
+
+    pMsg = (tSirCapTsfParams*)pMsgBuf;
+    if (pMsg == NULL) {
+        limLog(pMac, LOGE, FL("NULL pMsg"));
+        return eSIR_FAILURE;
+    }
+
+    psessionEntry = peFindSessionByBssid(pMac, pMsg->bssid, &sessionId);
+    if (NULL == psessionEntry)
+    {
+        limLog(pMac, LOGE, FL("NULL psessionEntry"));
+        return eSIR_FAILURE;
+    }
+    cap_tsf_params = (tSirCapTsfParams *)
+                       vos_mem_malloc(sizeof(*cap_tsf_params));
+    if (!cap_tsf_params) {
+        limLog(pMac, LOGE, FL(" Unable to allocate memory for cap tsf params"));
+        return eSIR_MEM_ALLOC_FAILED;
+    }
+    vos_mem_copy (cap_tsf_params, pMsg, sizeof(*cap_tsf_params));
+    cap_tsf_params->bss_idx = psessionEntry->bssIdx;
+
+    msg.type = WDA_CAP_TSF_REQ;
+    msg.reserved = 0;
+    msg.bodyptr = cap_tsf_params;
+    msg.bodyval = 0;
+    if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg))
+    {
+        limLog(pMac, LOGE, FL("lim_process_sme_cap_tsf_req failed\n"));
+        vos_mem_free(cap_tsf_params);
+        return eSIR_FAILURE;
+    }
+
+    return eSIR_SUCCESS;
+}
+
+/**
+ * lim_process_sme_get_tsf_req()- send get tsf request to WDA
+ * Get bss_idx from PE and fill in cap tsf request.
+ * @pMac:Mac ctx
+ * @pMsgBuf: message buffer from sme
+ * Returns success on post to WDA, otherwise failure
+ */
+tSirRetStatus lim_process_sme_get_tsf_req(tpAniSirGlobal pMac,
+                                          tANI_U32 *pMsgBuf)
+{
+    tSirCapTsfParams *pMsg = NULL;
+    tpPESession psessionEntry = NULL;
+    uint8_t sessionId;
+    tSirMsgQ               msg;
+    tSirCapTsfParams      *get_tsf_params;
+
+    pMsg = (tSirCapTsfParams*)pMsgBuf;
+    if (pMsg == NULL) {
+        limLog(pMac, LOGE, FL("NULL pMsg"));
+        return eSIR_FAILURE;
+    }
+
+    psessionEntry = peFindSessionByBssid(pMac, pMsg->bssid, &sessionId);
+    if (NULL == psessionEntry)
+    {
+        limLog(pMac, LOGE, FL("NULL psessionEntry"));
+        return eSIR_FAILURE;
+    }
+    get_tsf_params = (tSirCapTsfParams *)
+                    vos_mem_malloc(sizeof(*get_tsf_params));
+    if (!get_tsf_params) {
+        limLog(pMac, LOGE, FL(" Unable to allocate memory for cap tsf params"));
+        return eSIR_MEM_ALLOC_FAILED;
+    }
+    vos_mem_copy (get_tsf_params, pMsg, sizeof(*get_tsf_params));
+    get_tsf_params->bss_idx = psessionEntry->bssIdx;
+
+    msg.type = WDA_GET_TSF_REQ;
+    msg.reserved = 0;
+    msg.bodyptr = get_tsf_params;
+    msg.bodyval = 0;
+    if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg))
+    {
+        limLog(pMac, LOGE, FL("lim_process_sme_cap_tsf_req failed\n"));
+        vos_mem_free(get_tsf_params);
+        return eSIR_FAILURE;
+    }
+
+    return eSIR_SUCCESS;
+}
diff --git a/CORE/MAC/src/pe/lim/limProcessMessageQueue.c b/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
index 262a95b..abc8bad 100644
--- a/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
+++ b/CORE/MAC/src/pe/lim/limProcessMessageQueue.c
@@ -2496,6 +2496,18 @@
          vos_mem_free((v_VOID_t*)limMsg->bodyptr);
          limMsg->bodyptr = NULL;
          break;
+
+    case eWNI_SME_CAP_TSF_REQ:
+        lim_process_sme_cap_tsf_req(pMac, limMsg->bodyptr);
+        vos_mem_free((v_VOID_t*)limMsg->bodyptr);
+        limMsg->bodyptr = NULL;
+        break;
+
+    case eWNI_SME_GET_TSF_REQ:
+        lim_process_sme_get_tsf_req(pMac, limMsg->bodyptr);
+        vos_mem_free((v_VOID_t*)limMsg->bodyptr);
+        limMsg->bodyptr = NULL;
+        break;
     default:
         vos_mem_free((v_VOID_t*)limMsg->bodyptr);
         limMsg->bodyptr = NULL;
diff --git a/CORE/MAC/src/pe/lim/limTypes.h b/CORE/MAC/src/pe/lim/limTypes.h
index a375494..feaf1ed 100644
--- a/CORE/MAC/src/pe/lim/limTypes.h
+++ b/CORE/MAC/src/pe/lim/limTypes.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.
  *
@@ -1072,5 +1072,11 @@
                                                  tANI_U32 *pMsgBuf);
 tSirRetStatus limProcessSmeDelAllTdlsPeers(tpAniSirGlobal pMac,
                                            tANI_U32 *pMsgBuf);
+
+tSirRetStatus lim_process_sme_cap_tsf_req(tpAniSirGlobal pMac,
+                                          tANI_U32 *pMsgBuf);
+
+tSirRetStatus lim_process_sme_get_tsf_req(tpAniSirGlobal pMac,
+                                          tANI_U32 *pMsgBuf);
 #endif /* __LIM_TYPES_H */
 
diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h
index ba5185b..2ede8eb 100644
--- a/CORE/SME/inc/sme_Api.h
+++ b/CORE/SME/inc/sme_Api.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.
  *
@@ -4012,4 +4012,15 @@
 
 eHalStatus sme_update_hb_threshold(tHalHandle hHal, tANI_U32 cfgId,
                        tANI_U8 hbThresh, eCsrBand eBand);
+
+eHalStatus sme_capture_tsf_req(tHalHandle hHal,
+                               tSirCapTsfParams capTsfParams);
+
+eHalStatus sme_get_tsf_req(tHalHandle hHal,
+                           tSirCapTsfParams capTsfParams);
+
+eHalStatus sme_set_tsfcb(tHalHandle hHal,
+                         tsf_rsp_cb rsp_cb, struct stsf *pTsf,
+                         void *pcallbackcontext);
+
 #endif //#if !defined( __SME_API_H )
diff --git a/CORE/SME/inc/sme_Trace.h b/CORE/SME/inc/sme_Trace.h
index 9967cac..d5a4ba0 100644
--- a/CORE/SME/inc/sme_Trace.h
+++ b/CORE/SME/inc/sme_Trace.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -146,6 +146,8 @@
     TRACE_CODE_SME_RX_HDD_LPHB_CONFIG_REQ,
 #endif /* FEATURE_WLAN_LPHB */
     TRACE_CODE_SME_RX_HDD_ROAM_DEL_PMKIDCACHE,
+    TRACE_CODE_SME_TX_HDD_CAP_TSF_REQ,
+    TRACE_CODE_SME_TX_HDD_GET_TSF_REQ,
     /* New trace commands to be added before this comment not at the end */
     /* Trace codes for SME commands */
     TRACE_CODE_SME_COMMAND = 250,
diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c
index 4765601..69a99fa 100644
--- a/CORE/SME/src/sme_common/sme_Api.c
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -14923,4 +14923,135 @@
 
     return VOS_STATUS_SUCCESS;
 }
+
 #endif /* WLAN_FEATURE_APFIND */
+
+/**
+ * sme_capture_tsf_req() - send tsf capture request to firmware
+ * @hHal: hal handle.
+ * @cap_tsf_params: capture tsf request params.
+ *
+ * Return: hal status.
+ */
+eHalStatus sme_capture_tsf_req(tHalHandle hHal, tSirCapTsfParams cap_tsf_params)
+{
+    eHalStatus          status    = eHAL_STATUS_SUCCESS;
+    tpAniSirGlobal      pMac      = PMAC_STRUCT(hHal);
+    vos_msg_t           vosMessage;
+    tpSirCapTsfParams   tsf_params = NULL;
+    VOS_STATUS vos_status;
+    tCsrRoamSession *pSession;
+
+    MTRACE(vos_trace(VOS_MODULE_ID_SME,
+                     TRACE_CODE_SME_TX_HDD_CAP_TSF_REQ, NO_SESSION, 0));
+    if (eHAL_STATUS_SUCCESS == ( status = sme_AcquireGlobalLock(&pMac->sme)))
+    {
+        pSession = CSR_GET_SESSION(pMac, cap_tsf_params.session_id);
+        if (!pSession)
+        {
+            smsLog(pMac, LOGE, FL("session %d not found"),
+                  cap_tsf_params.bss_idx);
+            sme_ReleaseGlobalLock( &pMac->sme );
+            return eHAL_STATUS_FAILURE;
+        }
+
+        tsf_params = (tpSirCapTsfParams)
+                        vos_mem_malloc(sizeof(*tsf_params));
+
+        if (NULL == tsf_params)
+        {
+           VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+                     "%s: Not able to allocate memory for sme_capture_tsf_req",
+                       __func__);
+           sme_ReleaseGlobalLock( &pMac->sme );
+           return eHAL_STATUS_FAILURE;
+        }
+        vos_mem_copy(&tsf_params->bssid, &pSession->connectedProfile.bssid,
+                     sizeof(tsf_params->bssid));
+
+        tsf_params->tsf_rsp_cb_func  = cap_tsf_params.tsf_rsp_cb_func;
+        tsf_params->tsf_rsp_cb_ctx  = cap_tsf_params.tsf_rsp_cb_ctx;
+
+        /* serialize the req through MC thread */
+        /* TODO: check if callback is required */
+        vosMessage.bodyptr = tsf_params;
+        vosMessage.type    = eWNI_SME_CAP_TSF_REQ;
+
+        vos_status = vos_mq_post_message(VOS_MQ_ID_PE, &vosMessage);
+
+        if (!VOS_IS_STATUS_SUCCESS(vos_status))
+        {
+           VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+                     "%s: Post Set TM Level MSG fail", __func__);
+           vos_mem_free(tsf_params);
+           status = eHAL_STATUS_FAILURE;
+        }
+        sme_ReleaseGlobalLock( &pMac->sme );
+    }
+    return(status);
+}
+
+/**
+ * sme_get_tsf_req() - send tsf get request to firmware
+ * @hHal: hal handle.
+ * @cap_tsf_params: capture tsf request params.
+ *
+ * Return: hal status.
+ */
+eHalStatus sme_get_tsf_req(tHalHandle hHal, tSirCapTsfParams cap_tsf_params)
+{
+    eHalStatus          status    = eHAL_STATUS_SUCCESS;
+    tpAniSirGlobal      pMac      = PMAC_STRUCT(hHal);
+    vos_msg_t           vosMessage;
+    tpSirCapTsfParams   tsf_params = NULL;
+    VOS_STATUS          vosStatus;
+    tCsrRoamSession *pSession;
+
+    MTRACE(vos_trace(VOS_MODULE_ID_SME,
+                     TRACE_CODE_SME_TX_HDD_GET_TSF_REQ, NO_SESSION, 0));
+
+    if (eHAL_STATUS_SUCCESS == (status = sme_AcquireGlobalLock(&pMac->sme)))
+    {
+        pSession = CSR_GET_SESSION(pMac, cap_tsf_params.session_id);
+
+        if (!pSession)
+        {
+            smsLog(pMac, LOGE, FL("session %d not found"),
+                  cap_tsf_params.bss_idx);
+            sme_ReleaseGlobalLock(&pMac->sme);
+            return eHAL_STATUS_FAILURE;
+        }
+
+        tsf_params = (tpSirCapTsfParams)
+                      vos_mem_malloc(sizeof(*tsf_params));
+        if (NULL == tsf_params)
+        {
+           VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+                     "%s: Not able to allocate memory for sme_capture_tsf_req",
+                       __func__);
+           sme_ReleaseGlobalLock(&pMac->sme);
+           return eHAL_STATUS_FAILURE;
+        }
+
+        vos_mem_copy(&tsf_params->bssid, &pSession->connectedProfile.bssid,
+                     sizeof(tsf_params->bssid));
+        tsf_params->tsf_rsp_cb_func = cap_tsf_params.tsf_rsp_cb_func;
+        tsf_params->tsf_rsp_cb_ctx  = cap_tsf_params.tsf_rsp_cb_ctx;
+
+        /* serialize the req through MC thread */
+        /* TODO: check if callback is required */
+        vosMessage.bodyptr = tsf_params;
+        vosMessage.type    = eWNI_SME_GET_TSF_REQ;
+
+        vosStatus = vos_mq_post_message(VOS_MQ_ID_PE, &vosMessage);
+        if (!VOS_IS_STATUS_SUCCESS(vosStatus))
+        {
+           VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+                     "%s: Post Set TM Level MSG fail", __func__);
+           vos_mem_free(tsf_params);
+           status = eHAL_STATUS_FAILURE;
+        }
+        sme_ReleaseGlobalLock(&pMac->sme);
+    }
+    return(status);
+}
diff --git a/CORE/SYS/legacy/src/utils/src/macTrace.c b/CORE/SYS/legacy/src/utils/src/macTrace.c
index a805b43..4b2dcd4 100644
--- a/CORE/SYS/legacy/src/utils/src/macTrace.c
+++ b/CORE/SYS/legacy/src/utils/src/macTrace.c
@@ -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.
  *
@@ -573,6 +573,8 @@
         CASE_RETURN_STRING(eWNI_SME_SET_TDLS_2040_BSSCOEX_REQ);
         CASE_RETURN_STRING(eWNI_SME_REGISTER_MGMT_FRAME_CB);
         CASE_RETURN_STRING(eWNI_SME_MSG_TYPES_END);
+        CASE_RETURN_STRING(eWNI_SME_CAP_TSF_REQ);
+        CASE_RETURN_STRING(eWNI_SME_GET_TSF_REQ);
         default:
             return( (tANI_U8*)"UNKNOWN" );
             break;
@@ -915,6 +917,8 @@
         CASE_RETURN_STRING(WDA_SET_MDNS_RESPONSE_CMD);
         CASE_RETURN_STRING(WDA_GET_MDNS_STATUS_CMD);
 #endif
+        CASE_RETURN_STRING(WDA_CAP_TSF_REQ);
+        CASE_RETURN_STRING(WDA_GET_TSF_REQ);
         default:
             return((tANI_U8*) "UNKNOWN" );
             break;
diff --git a/CORE/WDA/inc/wlan_qct_wda.h b/CORE/WDA/inc/wlan_qct_wda.h
index 1b77fbf..6f0d9b7 100644
--- a/CORE/WDA/inc/wlan_qct_wda.h
+++ b/CORE/WDA/inc/wlan_qct_wda.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.
  *
@@ -1380,6 +1380,10 @@
 #define WDA_AP_FIND_IND                       SIR_HAL_AP_FIND_IND
 #endif /* WLAN_FEATURE_APFIND */
 
+#define WDA_CAP_TSF_REQ                       SIR_HAL_CAP_TSF_REQ
+#define WDA_GET_TSF_REQ                       SIR_HAL_GET_TSF_REQ
+
+
 #define HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME 0x40 // Bit 6 will be used to control BD rate for Management frames
 
 #define halTxFrame(hHal, pFrmBuf, frmLen, frmType, txDir, tid, pCompFunc, pData, txFlag) \
@@ -2199,4 +2203,9 @@
 
 void WDA_SetMgmtPktViaWQ5(v_BOOL_t sendMgmtPktViaWQ5);
 
+#define CAP_TSF_REQUEST 0
+#define GET_TSF_REQUEST 1
+
+VOS_STATUS WDA_ProcessCapTsfReq(tWDA_CbContext *pWDA, tSirCapTsfParams *params);
+VOS_STATUS WDA_ProcessGetTsfReq(tWDA_CbContext *pWDA, tSirCapTsfParams *params);
 #endif
diff --git a/CORE/WDA/src/wlan_qct_wda.c b/CORE/WDA/src/wlan_qct_wda.c
index 4368612..81b9574 100644
--- a/CORE/WDA/src/wlan_qct_wda.c
+++ b/CORE/WDA/src/wlan_qct_wda.c
@@ -17403,6 +17403,17 @@
           break;
       }
 #endif
+      case WDA_CAP_TSF_REQ:
+      {
+          WDA_ProcessCapTsfReq(pWDA, (tSirCapTsfParams *)
+                               pMsg->bodyptr);
+          break;
+      }
+      case WDA_GET_TSF_REQ:
+      {
+          WDA_ProcessGetTsfReq(pWDA, (tSirCapTsfParams *)pMsg->bodyptr);
+          break;
+      }
       default:
       {
          VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
@@ -23192,5 +23203,274 @@
     vos_mem_free(params);
     return CONVERT_WDI2VOS_STATUS(status) ;
 }
-
 #endif
+/*
+ * WDA_CapTsfRspCb : handle response for tsf requests
+ * @wdi_rsp : Response from WDI for tsf requests
+ * @user_data: pointer to user data
+ * Returns: None
+ */
+void WDA_CapTsfRspCb (wdi_cap_tsf_rsp_t *wdi_rsp, void *user_data)
+{
+
+    tWDA_ReqParams *wda_params = (tWDA_ReqParams *)user_data;
+    tSirCapTsfParams *cap_tsf_params;
+    struct stsf *stsf_temp;
+    VOS_STATUS status;
+
+    VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+              "<------ %s " ,__func__);
+
+    if (NULL == wda_params) {
+        VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                  "%s: pWdaParams received NULL", __func__);
+        VOS_ASSERT(0);
+        return;
+    }
+
+    if (NULL == wda_params->wdaMsgParam) {
+        VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                  "%s: pWdaParams->wdaMsgParam is NULL", __func__);
+        VOS_ASSERT(0);
+        vos_mem_free(wda_params->wdaWdiApiMsgParam);
+        vos_mem_free(wda_params);
+        return;
+    }
+
+    stsf_temp = (struct stsf *)vos_mem_malloc(sizeof(*stsf_temp));
+    if (NULL == stsf_temp) {
+        VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                  "%s: Unable to allocate tsf struct", __func__);
+        VOS_ASSERT(0);
+        vos_mem_free(wda_params->wdaWdiApiMsgParam);
+        vos_mem_free(wda_params->wdaMsgParam);
+        vos_mem_free(wda_params);
+        return;
+    }
+    cap_tsf_params = (tSirCapTsfParams *)wda_params->wdaMsgParam;
+    stsf_temp->session_id = cap_tsf_params->bss_idx;
+    stsf_temp->set_tsf_req = true;
+    stsf_temp->tsf_req_status = wdi_rsp->status;
+
+    if (cap_tsf_params->tsf_rsp_cb_func) {
+        cap_tsf_params->tsf_rsp_cb_func (
+                        cap_tsf_params->tsf_rsp_cb_ctx, stsf_temp);
+    }
+    else {
+        VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                  "%s: tsf callback is NULL", __func__);
+        vos_mem_free(stsf_temp);
+    }
+    status = CONVERT_WDI2VOS_STATUS(wdi_rsp->status);
+    if (status) {
+        VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                  "%s: Capture TSF failed with status=%d", __func__,
+                   status);
+        VOS_ASSERT(0);
+    }
+    vos_mem_free(wda_params->wdaWdiApiMsgParam);
+    vos_mem_free(wda_params->wdaMsgParam);
+    vos_mem_free(wda_params);
+    return;
+}
+
+/*
+ * WDA_GetTsfRspCb : handle response for get tsf request
+ * @wdi_rsp : Response from WDI for tsf requests
+ * @user_data: pointer to user data
+ * Returns: None
+ */
+void WDA_GetTsfRspCb (wdi_cap_tsf_rsp_t *wdi_rsp, void *user_data)
+{
+
+    tWDA_ReqParams *wda_params = (tWDA_ReqParams *)user_data;
+    tSirCapTsfParams *cap_tsf_params;
+    struct stsf *stsf_temp;
+    VOS_STATUS status;
+
+    VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+              "<------ %s " ,__func__);
+
+    if (NULL == wda_params) {
+        VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                  "%s: pWdaParams received NULL", __func__);
+        VOS_ASSERT(0);
+        return;
+    }
+
+    if (NULL == wda_params->wdaMsgParam) {
+        VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                  "%s: pWdaParams->wdaMsgParam is NULL", __func__);
+        VOS_ASSERT(0);
+        vos_mem_free(wda_params->wdaWdiApiMsgParam);
+        vos_mem_free(wda_params);
+        return;
+    }
+
+    stsf_temp = (struct stsf *)vos_mem_malloc(sizeof(*stsf_temp));
+    if (NULL == stsf_temp) {
+        VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                  "%s: Unable to allocate tsf struct", __func__);
+        VOS_ASSERT(0);
+        vos_mem_free(wda_params->wdaWdiApiMsgParam);
+        vos_mem_free(wda_params->wdaMsgParam);
+        vos_mem_free(wda_params);
+        return;
+    }
+    cap_tsf_params = (tSirCapTsfParams *)wda_params->wdaMsgParam;
+    stsf_temp->session_id = cap_tsf_params->bss_idx;
+    /* Indicate to upper layer that this is a get request */
+    stsf_temp->set_tsf_req = false;
+    stsf_temp->tsf_low = wdi_rsp->tsf_lo;
+    stsf_temp->tsf_high = wdi_rsp->tsf_hi;
+    stsf_temp->tsf_req_status = wdi_rsp->status;
+
+    if (cap_tsf_params->tsf_rsp_cb_func) {
+        cap_tsf_params->tsf_rsp_cb_func (
+                        cap_tsf_params->tsf_rsp_cb_ctx, stsf_temp);
+    }
+    else {
+        VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                  "%s: tsf callback is NULL", __func__);
+        vos_mem_free(stsf_temp);
+    }
+    status = CONVERT_WDI2VOS_STATUS(wdi_rsp->status);
+    if (status) {
+        VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                  "%s: Capture TSF failed with status=%d", __func__,
+                   status);
+        VOS_ASSERT(0);
+    }
+    vos_mem_free(wda_params->wdaWdiApiMsgParam);
+    vos_mem_free(wda_params->wdaMsgParam);
+    vos_mem_free(wda_params);
+    return;
+}
+/*
+ * FUNCTION: WDA_ProcessCapTsfReq
+ * Send capture tsf request to FW.
+ */
+VOS_STATUS WDA_ProcessCapTsfReq(tWDA_CbContext *pWDA, tSirCapTsfParams *params)
+{
+    WDI_Status status = WDI_STATUS_SUCCESS;
+    wdi_cap_tsf_params_t  *pWDICapTsfReqType;
+    tWDA_ReqParams *pWdaParams ;
+
+    VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+                                           "<------ %s " ,__func__);
+    if(NULL == params)
+    {
+        VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                "%s: cap tsf params NULL", __func__);
+        VOS_ASSERT(0) ;
+        return -EINVAL;
+    }
+
+    pWDICapTsfReqType = (wdi_cap_tsf_params_t *)vos_mem_malloc(
+                                       sizeof(*pWDICapTsfReqType));
+    if(NULL == pWDICapTsfReqType)
+    {
+        VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                             "%s: VOS MEM Alloc Failure", __func__);
+        VOS_ASSERT(0);
+        vos_mem_free(params);
+        return VOS_STATUS_E_NOMEM;
+    }
+    pWdaParams = (tWDA_ReqParams *)vos_mem_malloc(sizeof(*pWdaParams)) ;
+    if(NULL == pWdaParams)
+    {
+        VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                             "%s: VOS MEM Alloc Failure", __func__);
+        VOS_ASSERT(0);
+        vos_mem_free(pWDICapTsfReqType);
+        vos_mem_free(params);
+        return VOS_STATUS_E_NOMEM;
+    }
+
+    pWDICapTsfReqType->bss_idx = params->bss_idx;
+    pWDICapTsfReqType->capTSFget = CAP_TSF_REQUEST;
+
+    pWdaParams->pWdaContext = pWDA;
+    pWdaParams->wdaMsgParam = params;
+    pWdaParams->wdaWdiApiMsgParam = (void *)pWDICapTsfReqType;
+
+    status = wdi_process_cap_tsf_req(pWDICapTsfReqType,
+                                     (wdi_tsf_rsp_cb)WDA_CapTsfRspCb,
+                                      pWdaParams);
+
+    if(IS_WDI_STATUS_FAILURE(status))
+    {
+        VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                "Failure in sendind WifiConfigReq, free all the memory" );
+        vos_mem_free(pWdaParams->wdaWdiApiMsgParam) ;
+        vos_mem_free(pWdaParams->wdaMsgParam);
+        vos_mem_free(pWdaParams);
+        vos_mem_free(params);
+    }
+    return CONVERT_WDI2VOS_STATUS(status) ;
+}
+
+/*
+ * FUNCTION: WDA_ProcessGetTsfReq
+ * Send capture tsf request to FW.
+ */
+VOS_STATUS WDA_ProcessGetTsfReq(tWDA_CbContext *pWDA, tSirCapTsfParams *params)
+{
+    WDI_Status status = WDI_STATUS_SUCCESS;
+    wdi_cap_tsf_params_t  *pWDIGetTsfReqType;
+    tWDA_ReqParams *pWdaParams ;
+
+    VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO,
+                                           "<------ %s " ,__func__);
+    if(NULL == params)
+    {
+        VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                "%s: cap tsf params NULL", __func__);
+        VOS_ASSERT(0) ;
+        return VOS_STATUS_E_INVAL;
+    }
+
+    pWDIGetTsfReqType = (wdi_cap_tsf_params_t *)vos_mem_malloc(
+                                       sizeof(wdi_cap_tsf_params_t));
+    if(NULL == pWDIGetTsfReqType)
+    {
+        VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                             "%s: VOS MEM Alloc Failure", __func__);
+        VOS_ASSERT(0);
+        vos_mem_free(params);
+        return VOS_STATUS_E_INVAL;
+    }
+    pWdaParams = (tWDA_ReqParams *)vos_mem_malloc(sizeof(tWDA_ReqParams)) ;
+    if(NULL == pWdaParams)
+    {
+        VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                             "%s: VOS MEM Alloc Failure", __func__);
+        VOS_ASSERT(0);
+        vos_mem_free(pWDIGetTsfReqType);
+        vos_mem_free(params);
+        return VOS_STATUS_E_NOMEM;
+    }
+
+    pWDIGetTsfReqType->bss_idx = params->bss_idx;
+    /* Indicate that this is a get request */
+    pWDIGetTsfReqType->capTSFget = GET_TSF_REQUEST;
+
+    pWdaParams->pWdaContext = pWDA;
+    pWdaParams->wdaMsgParam = params;
+    pWdaParams->wdaWdiApiMsgParam = (void *)pWDIGetTsfReqType;
+
+    status = wdi_process_get_tsf_req(pWDIGetTsfReqType,
+                                     (wdi_tsf_rsp_cb)WDA_GetTsfRspCb,
+                                      pWdaParams);
+
+    if(IS_WDI_STATUS_FAILURE(status))
+    {
+        VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR,
+                "Failure in sendind WifiConfigReq, free all the memory" );
+        vos_mem_free(pWdaParams->wdaWdiApiMsgParam) ;
+        vos_mem_free(pWdaParams->wdaMsgParam);
+        vos_mem_free(pWdaParams);
+        vos_mem_free(params);
+    }
+    return CONVERT_WDI2VOS_STATUS(status) ;
+}
diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi.h b/CORE/WDI/CP/inc/wlan_qct_wdi.h
index fc3dfe7..fd7912b 100644
--- a/CORE/WDI/CP/inc/wlan_qct_wdi.h
+++ b/CORE/WDI/CP/inc/wlan_qct_wdi.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.
  *
@@ -6664,6 +6664,28 @@
     wpt_uint8 key[64];
 };
 
+/**
+ * wdi_cap_tsf_params_t - wdi capture tsf params
+ * @bssidx: bss index
+ * @capTSFget: whether get/set request
+ *
+ */
+ typedef struct {
+   wpt_uint8 bss_idx;
+   wpt_uint8  capTSFget;
+} wdi_cap_tsf_params_t;
+
+/**
+ * wdi_cap_tsf_rsp_t - capture tsf response
+ * @bssidx: bss index
+ * @capTSFget: whether get/set request
+ *
+ */
+ typedef struct {
+    wpt_uint32 status;
+    wpt_uint32 tsf_lo;
+    wpt_uint32 tsf_hi;
+} wdi_cap_tsf_rsp_t;
 
 /*----------------------------------------------------------------------------
  *   WDI callback types
@@ -8635,6 +8657,8 @@
 typedef void (*wdi_get_stats_rsp_cb)(void *event_data,void *user_data);
 #endif /* MDNS_OFFLOAD */
 
+typedef void (*wdi_tsf_rsp_cb)(void *event_data,void *user_data);
+
 
 /*========================================================================
  *     Function Declarations and Documentation
@@ -12475,4 +12499,15 @@
 );
 #endif /* MDNS_OFFLOAD */
 
+WDI_Status
+wdi_process_cap_tsf_req (wdi_cap_tsf_params_t *wdi_cap_tsf_req,
+                         wdi_tsf_rsp_cb wdi_tsf_rsp_callback,
+                         void *user_data);
+
+WDI_Status
+wdi_process_get_tsf_req (wdi_cap_tsf_params_t *wdi_get_tsf_req,
+                         wdi_tsf_rsp_cb wdi_tsf_rsp_callback,
+                         void *user_data);
+
+
 #endif /* #ifndef WLAN_QCT_WDI_H */
diff --git a/CORE/WDI/CP/inc/wlan_qct_wdi_i.h b/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
index 0f01a78..034fe71 100644
--- a/CORE/WDI/CP/inc/wlan_qct_wdi_i.h
+++ b/CORE/WDI/CP/inc/wlan_qct_wdi_i.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.
  *
@@ -500,6 +500,9 @@
   WDI_MDNS_RESP_OFFLOAD_REQ                      = 121,
   WDI_MDNS_STATS_OFFLOAD_REQ                     = 122,
 
+  WDI_CAP_TSF_REQ                                = 123,
+  WDI_GET_TSF_REQ                                = 124,
+
   WDI_MAX_REQ,
 
   /*Send a suspend Indication down to HAL*/
@@ -885,6 +888,7 @@
   WDI_MDNS_FQDN_OFFLOAD_RSP                      = 120,
   WDI_MDNS_RESP_OFFLOAD_RSP                      = 121,
   WDI_MDNS_STATS_OFFLOAD_RSP                     = 122,
+  WDI_CAPTURE_GET_TSF_TSTAMP_RSP                 = 123,
 
   /*-------------------------------------------------------------------------
     Indications
@@ -6808,5 +6812,26 @@
   WDI_EventInfoType*     pEventData
 );
 #endif
+
+WDI_Status
+wdi_cap_tsf_req
+(
+    WDI_ControlBlockType *wdi_ctx,
+    WDI_EventInfoType *event_data
+);
+
+WDI_Status
+wdi_get_tsf_req
+(
+    WDI_ControlBlockType *wdi_ctx,
+    WDI_EventInfoType *event_data
+);
+WDI_Status
+wdi_get_tsf_rsp
+(
+    WDI_ControlBlockType *wdi_ctx,
+    WDI_EventInfoType *event_data
+);
+
 #endif /*WLAN_QCT_WDI_I_H*/
 
diff --git a/CORE/WDI/CP/src/wlan_qct_wdi.c b/CORE/WDI/CP/src/wlan_qct_wdi.c
index 4e36426..5ed7a7a 100644
--- a/CORE/WDI/CP/src/wlan_qct_wdi.c
+++ b/CORE/WDI/CP/src/wlan_qct_wdi.c
@@ -535,6 +535,8 @@
     NULL,
     NULL,
 #endif /* MDNS_OFFLOAD */
+  wdi_cap_tsf_req,   /* WDI_CAP_TSF_REQ */
+  wdi_get_tsf_req,   /* WDI_GET_TSF_REQ */
 
   /*-------------------------------------------------------------------------
     Indications
@@ -878,7 +880,9 @@
     NULL,
     NULL,
     NULL,
-#endif /* MDNS_OFFLOAD */
+#endif  /* MDNS_OFFLOAD */
+   wdi_get_tsf_rsp, /* WDI_CAPTURE_GET_TSF_TSTAMP_RSP */
+
   /*---------------------------------------------------------------------
     Indications
   ---------------------------------------------------------------------*/
@@ -1710,6 +1714,7 @@
 #ifdef DHCP_SERVER_OFFLOAD
     CASE_RETURN_STRING (WDI_DHCP_SERVER_OFFLOAD_RSP);
 #endif /* DHCP_SERVER_OFFLOAD */
+    CASE_RETURN_STRING (WDI_CAPTURE_GET_TSF_TSTAMP_RSP);
     default:
         return "Unknown WDI MessageId";
   }
@@ -25041,6 +25046,10 @@
   case WDI_MDNS_STATS_OFFLOAD_REQ:
       return WLAN_HAL_MDNS_STATS_OFFLOAD_REQ;
 #endif /* MDNS_OFFLOAD */
+  case WDI_CAP_TSF_REQ:
+     return WLAN_HAL_CAPTURE_GET_TSF_TSTAMP;
+  case WDI_GET_TSF_REQ:
+     return WLAN_HAL_CAPTURE_GET_TSF_TSTAMP;
   default:
     return WLAN_HAL_MSG_MAX;
   }
@@ -25428,6 +25437,8 @@
   case WLAN_HAL_QRF_PREF_NETW_FOUND_IND:
     return WDI_HAL_QRF_PREF_NETWORK_FOUND_IND;
 #endif
+  case WLAN_HAL_CAPTURE_GET_TSF_TSTAMP_RSP:
+    return WDI_CAPTURE_GET_TSF_TSTAMP_RSP;
   default:
     return eDRIVER_TYPE_MAX;
   }
@@ -39412,4 +39423,249 @@
 
     return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData);
 }
+
+/**
+ *  wdi_process_cap_tsf_req() - Send Capture tsf request to FW.
+ *
+ *  @pWDICtx: pointer to the WLAN DAL context
+ *  @pEventData: pointer to the event information structure
+ *
+ *  Return: WDI_Status enumeration
+ */
+WDI_Status wdi_process_cap_tsf_req(wdi_cap_tsf_params_t *wdi_cap_tsf_req,
+                                   wdi_tsf_rsp_cb wdi_cap_tsf_rsp_callback,
+                                   void *user_data)
+{
+    WDI_EventInfoType wdiEventData;
+
+    if (eWLAN_PAL_FALSE == gWDIInitialized)
+    {
+        WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
+                "WDI API call before module is initialized - Fail req");
+        return WDI_STATUS_E_NOT_ALLOWED;
+    }
+
+    wdiEventData.wdiRequest = WDI_CAP_TSF_REQ;
+    wdiEventData.pEventData = wdi_cap_tsf_req;
+    wdiEventData.uEventDataSize  = sizeof(*wdi_cap_tsf_req);
+    wdiEventData.pCBfnc = wdi_cap_tsf_rsp_callback;
+    wdiEventData.pUserData = user_data;
+
+    return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData);
+}
+/**
+ *  wdi_process_get_tsf_req() - Send Get tsf request to FW.
+ *
+ *  @pWDICtx: pointer to the WLAN DAL context
+ *  @pEventData: pointer to the event information structure
+ *
+ *  Return: WDI_Status enumeration
+ */
+WDI_Status wdi_process_get_tsf_req(wdi_cap_tsf_params_t *wdi_get_tsf_req,
+                                   wdi_tsf_rsp_cb wdi_tsf_rsp_callback,
+                                   void *user_data)
+{
+    WDI_EventInfoType wdiEventData;
+
+    if (eWLAN_PAL_FALSE == gWDIInitialized)
+    {
+        WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR,
+                "WDI API call before module is initialized - Fail req");
+        return WDI_STATUS_E_NOT_ALLOWED;
+    }
+
+    wdiEventData.wdiRequest = WDI_GET_TSF_REQ;
+    wdiEventData.pEventData = wdi_get_tsf_req;
+    wdiEventData.uEventDataSize  = sizeof(*wdi_get_tsf_req);
+    wdiEventData.pCBfnc = wdi_tsf_rsp_callback;
+    wdiEventData.pUserData = user_data;
+
+    return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData);
+}
+
+/**
+ * wdi_cap_tsf_req() - wdi api for capture tsf request
+ * @wdi_ctx: pointer to wdi context
+ * @event_data: pointer to event data
+ *
+ * Return: WDI_Status
+ * WDI_STATUS_SUCCESS - success or else failure status
+ */
+WDI_Status wdi_cap_tsf_req (WDI_ControlBlockType *wdi_ctx,
+                            WDI_EventInfoType *event_data)
+{
+
+    wdi_cap_tsf_params_t *wdi_cap_tsf_req_info;
+    wpt_uint8 *buff  = NULL;
+    wpt_uint16 data_offset = 0;
+    wpt_uint16 size = 0;
+    WDI_Status wdi_status;
+    tHalCapTSFgetReqInd hal_cap_tsf_req;
+    wdi_tsf_rsp_cb wdi_tsf_rsp_callback;
+
+    VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO,
+              "%s: Enter",__func__ );
+    /* Sanity check */
+    if ((NULL == wdi_ctx) || (NULL == event_data) ||
+        (NULL == event_data->pEventData)) {
+
+        WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN,
+                   "%s: Invalid parameters", __func__);
+        WDI_ASSERT(0);
+        return WDI_STATUS_E_FAILURE;
+    }
+
+    wdi_cap_tsf_req_info = (wdi_cap_tsf_params_t *)
+                            event_data->pEventData;
+
+    /* Get message buffer */
+    if (( WDI_STATUS_SUCCESS !=
+          WDI_GetMessageBuffer(wdi_ctx,
+                               WDI_CAP_TSF_REQ,
+                               sizeof(hal_cap_tsf_req.
+                                      capTSFget),
+                               &buff, &data_offset, &size))||
+          (size < (data_offset +
+                   sizeof(hal_cap_tsf_req.capTSFget))))
+    {
+        WPAL_TRACE(eWLAN_MODULE_DAL_CTRL,  eWLAN_PAL_TRACE_LEVEL_FATAL,
+                   "Unable to get send buffer in GetTsfFrame Req");
+        WDI_ASSERT(0);
+        return WDI_STATUS_E_FAILURE;
+    }
+    hal_cap_tsf_req.capTSFget.uBssIdx = wdi_cap_tsf_req_info->bss_idx;
+    hal_cap_tsf_req.capTSFget.capTSFget = wdi_cap_tsf_req_info->capTSFget;
+
+    wdi_tsf_rsp_callback = (wdi_tsf_rsp_cb)event_data->pCBfnc;
+
+    wpalMemoryCopy(buff+data_offset,
+                   &hal_cap_tsf_req.capTSFget,
+                   sizeof(hal_cap_tsf_req.capTSFget));
+
+    wdi_status = WDI_SendMsg(wdi_ctx, buff, size,
+                             wdi_tsf_rsp_callback,
+                             event_data->pUserData,
+                             WDI_CAPTURE_GET_TSF_TSTAMP_RSP);
+
+    VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO,
+              "%s: Exit",__func__);
+
+    return wdi_status;
+}
+
+/**
+ * wdi_get_tsf_req() - wdi api for get tsf request
+ * @wdi_ctx: pointer to wdi context
+ * @event_data: pointer to event data
+ *
+ * Return: WDI_Status
+ * WDI_STATUS_SUCCESS - success or else failure status
+ */
+WDI_Status wdi_get_tsf_req (WDI_ControlBlockType *wdi_ctx,
+                            WDI_EventInfoType *event_data)
+{
+
+    wdi_cap_tsf_params_t *wdi_cap_tsf_req_info;
+    wpt_uint8 *buff  = NULL;
+    wpt_uint16 data_offset = 0;
+    wpt_uint16 size = 0;
+    WDI_Status wdi_status;
+    tHalCapTSFgetReqInd hal_cap_tsf_req;
+    wdi_tsf_rsp_cb wdi_tsf_rsp_callback;
+
+    VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO,
+              "%s: Enter",__func__ );
+    /* Sanity check */
+    if ((NULL == wdi_ctx) || (NULL == event_data) ||
+        (NULL == event_data->pEventData)) {
+
+        WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN,
+                   "%s: Invalid parameters", __func__);
+        WDI_ASSERT(0);
+        return WDI_STATUS_E_FAILURE;
+    }
+
+    wdi_cap_tsf_req_info = (wdi_cap_tsf_params_t *)
+                            event_data->pEventData;
+
+    /* Get message buffer */
+    if (( WDI_STATUS_SUCCESS !=
+          WDI_GetMessageBuffer(wdi_ctx,
+                               WDI_CAP_TSF_REQ,
+                               sizeof(hal_cap_tsf_req.
+                                      capTSFget),
+                               &buff, &data_offset, &size))||
+          (size < (data_offset +
+                   sizeof(hal_cap_tsf_req.capTSFget))))
+    {
+        WPAL_TRACE(eWLAN_MODULE_DAL_CTRL,  eWLAN_PAL_TRACE_LEVEL_FATAL,
+                   "Unable to get send buffer in GetTsfFrame Req");
+        WDI_ASSERT(0);
+        return WDI_STATUS_E_FAILURE;
+    }
+    hal_cap_tsf_req.capTSFget.uBssIdx = wdi_cap_tsf_req_info->bss_idx;
+    hal_cap_tsf_req.capTSFget.capTSFget = wdi_cap_tsf_req_info->capTSFget;
+
+    wdi_tsf_rsp_callback = (wdi_tsf_rsp_cb)event_data->pCBfnc;
+
+    wpalMemoryCopy(buff+data_offset,
+                   &hal_cap_tsf_req.capTSFget,
+                   sizeof(hal_cap_tsf_req.capTSFget));
+
+    wdi_status = WDI_SendMsg(wdi_ctx, buff, size,
+                             wdi_tsf_rsp_callback,
+                             event_data->pUserData,
+                             WDI_CAPTURE_GET_TSF_TSTAMP_RSP);
+
+    VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_INFO,
+              "%s: Exit",__func__);
+
+    return wdi_status;
+}
+
+/**
+ * wdi_get_tsf_rsp() - wdi api for the get tsf response
+ * @wdi_ctx: pointer to the wdi context
+ * @event_data: pointer to the event data
+ *
+ * Return: WDI_Status
+ *      WDI_STATUS_SUCCESS - success or else failure status
+ */
+WDI_Status
+wdi_get_tsf_rsp
+(
+    WDI_ControlBlockType *wdi_ctx,
+    WDI_EventInfoType *event_data
+)
+{
+        wdi_tsf_rsp_cb wdi_tsf_rsp_callback;
+
+        WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO,
+                   "%s: Enter ", __func__);
+        /*-------------------------------------------------------------------
+          Sanity check
+          -----------------------------------------------------------------*/
+        if ((NULL == wdi_ctx) || (NULL == event_data) ||
+            (NULL == event_data->pEventData))
+        {
+                WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN,
+                           "%s: Invalid parameters", __func__);
+                WDI_ASSERT(0);
+                return WDI_STATUS_E_FAILURE;
+        }
+
+        wdi_tsf_rsp_callback =
+                (wdi_tsf_rsp_cb)wdi_ctx->pfncRspCB;
+
+        if (wdi_tsf_rsp_callback)
+            wdi_tsf_rsp_callback((void *) event_data->pEventData,
+                                          wdi_ctx->pRspCBUserData);
+        else {
+            VOS_TRACE(VOS_MODULE_ID_WDI, VOS_TRACE_LEVEL_ERROR,
+                      "wdi_tsf_rsp_callback is NULL!");
+            return WDI_STATUS_E_FAILURE;
+        }
+
+        return WDI_STATUS_SUCCESS;
+}
 #endif
diff --git a/Kbuild b/Kbuild
index 438335d..a7d0f57 100644
--- a/Kbuild
+++ b/Kbuild
@@ -573,7 +573,8 @@
                 -DWLAN_FEATURE_EXTSCAN \
                 -DFEATURE_EXT_LL_STAT \
                 -DWLAN_VOWIFI_DEBUG \
-		-DDHCP_SERVER_OFFLOAD
+		-DDHCP_SERVER_OFFLOAD \
+		-DWLAN_FEATURE_TSF
 
 ifneq ($(CONFIG_PRONTO_WLAN),)
 CDEFINES += -DWCN_PRONTO