summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkaliu <kaliu@qti.qualcomm.com>2015-04-22 14:51:13 +0800
committerAnjaneeDevi Kapparapu <c_akappa@qti.qualcomm.com>2015-04-22 17:04:17 +0530
commit58afff5a4028b8a52a56f96ec45fdea35e29503e (patch)
tree5804e5ed484b4d2543a52316a70a10fef5e03534
parentd6667373b600ed00fc82de2a5d6a34ae5f16664a (diff)
qcacld: get tsf from fw.
Get tsf from fw. Provide ioctl interface cap_tsf/get_tsf. Driver issue wmi cmd to fw to realize capture/get. It can be used in station and softap mode. For sta, getting tsf from connected ap. For softap, it will generate tsf by- self. Change-Id: I00d30882bce2f49ee3de3fa189e094c04c0d9943 CRs-Fixed: 817527
-rw-r--r--CORE/HDD/inc/qc_sap_ioctl.h5
-rw-r--r--CORE/HDD/inc/wlan_hdd_main.h8
-rw-r--r--CORE/HDD/inc/wlan_hdd_tsf.h48
-rw-r--r--CORE/HDD/inc/wlan_hdd_wext.h32
-rw-r--r--CORE/HDD/src/wlan_hdd_hostapd.c75
-rwxr-xr-xCORE/HDD/src/wlan_hdd_main.c3
-rw-r--r--CORE/HDD/src/wlan_hdd_tsf.c207
-rw-r--r--CORE/HDD/src/wlan_hdd_wext.c89
-rw-r--r--CORE/MAC/inc/sirApi.h15
-rw-r--r--CORE/MAC/inc/wniApi.h1
-rw-r--r--CORE/SERVICES/COMMON/wma_api.h4
-rw-r--r--CORE/SERVICES/WMA/wma.c183
-rw-r--r--CORE/SME/inc/smeInternal.h4
-rw-r--r--CORE/SME/inc/sme_Api.h4
-rw-r--r--CORE/SME/src/sme_common/sme_Api.c38
-rw-r--r--Kbuild9
-rw-r--r--Kconfig4
17 files changed, 721 insertions, 8 deletions
diff --git a/CORE/HDD/inc/qc_sap_ioctl.h b/CORE/HDD/inc/qc_sap_ioctl.h
index 3adca88f5334..c690e263d139 100644
--- a/CORE/HDD/inc/qc_sap_ioctl.h
+++ b/CORE/HDD/inc/qc_sap_ioctl.h
@@ -140,7 +140,8 @@ typedef struct
#define QCSAP_IOCTL_SETPARAM (SIOCIWFIRSTPRIV+0)
#define QCSAP_IOCTL_GETPARAM (SIOCIWFIRSTPRIV+1)
/* (SIOCIWFIRSTPRIV+2) is unused */
-/* (SIOCIWFIRSTPRIV+3) is unused */
+#define QCSAP_IOCTL_SET_NONE_GET_THREE (SIOCIWFIRSTPRIV+3)
+#define WE_GET_TSF 1
#define QCSAP_IOCTL_GET_STAWPAIE (SIOCIWFIRSTPRIV+4)
#define QCSAP_IOCTL_SETWPAIE (SIOCIWFIRSTPRIV+5)
#define QCSAP_IOCTL_STOPBSS (SIOCIWFIRSTPRIV+6)
@@ -246,6 +247,8 @@ enum {
QCSAP_GET_FW_STATUS,
QCASAP_DUMP_STATS,
QCASAP_CLEAR_STATS,
+ QCSAP_CAP_TSF,
+ QCSAP_GET_TSF,
};
int iw_softap_get_channel_list(struct net_device *dev,
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index 42514b85fe79..7fa3e5ba7106 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -975,6 +975,14 @@ struct hdd_adapter_s
hdd_mon_ctx_t monitor;
}sessionCtx;
+#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;
+#endif
+
hdd_cfg80211_state_t cfg80211State;
#ifdef WLAN_FEATURE_PACKET_FILTERING
diff --git a/CORE/HDD/inc/wlan_hdd_tsf.h b/CORE/HDD/inc/wlan_hdd_tsf.h
new file mode 100644
index 000000000000..499cef8c22d6
--- /dev/null
+++ b/CORE/HDD/inc/wlan_hdd_tsf.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015 Qualcomm Atheros, Inc.
+ * All Rights Reserved.
+ * Qualcomm Atheros Confidential and Proprietary.
+ *
+ */
+
+#if !defined WLAN_HDD_TSF_H
+#define WLAN_HDD_TSF_H
+
+/*---------------------------------------------------------------------------
+ Include files
+ -------------------------------------------------------------------------*/
+#include <wlan_hdd_includes.h>
+
+/*---------------------------------------------------------------------------
+ Preprocessor definitions and constants
+ -------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+ Function declarations and documentation
+ -------------------------------------------------------------------------*/
+
+#ifdef WLAN_FEATURE_TSF
+void wlan_hdd_tsf_init(hdd_context_t *hdd_ctx);
+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_context_t *hdd_ctx)
+{
+ 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
diff --git a/CORE/HDD/inc/wlan_hdd_wext.h b/CORE/HDD/inc/wlan_hdd_wext.h
index 2715c1d4e24d..386b97ff0b9b 100644
--- a/CORE/HDD/inc/wlan_hdd_wext.h
+++ b/CORE/HDD/inc/wlan_hdd_wext.h
@@ -252,6 +252,38 @@ typedef enum
WEXT_SCAN_PENDING_MAX
} hdd_scan_pending_option_e;
+/**
+ * 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
+ */
+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
+};
+
+/**
+ * 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
+};
+
/*
* This structure contains the interface level (granularity)
* configuration information in support of wireless extensions.
diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c
index 114b52d824f7..78f8431300dc 100644
--- a/CORE/HDD/src/wlan_hdd_hostapd.c
+++ b/CORE/HDD/src/wlan_hdd_hostapd.c
@@ -95,6 +95,7 @@ extern int process_wma_set_command(int sessid, int paramid,
#include "vos_trace.h"
#include "wlan_hdd_cfg.h"
#include <wlan_hdd_wowl.h>
+#include "wlan_hdd_tsf.h"
#define IS_UP(_dev) \
(((_dev)->flags & (IFF_RUNNING|IFF_UP)) == (IFF_RUNNING|IFF_UP))
@@ -3088,6 +3089,62 @@ static __iw_softap_setparam(struct net_device *dev,
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_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;
+}
+
+
int
static iw_softap_setparam(struct net_device *dev,
struct iw_request_info *info,
@@ -3114,7 +3171,6 @@ static __iw_softap_getparam(struct net_device *dev,
eHalStatus status;
int ret = 0; /* success */
hdd_context_t *pHddCtx = NULL;
-
pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter);
status = wlan_hdd_validate_context(pHddCtx);
@@ -3302,11 +3358,15 @@ static __iw_softap_getparam(struct net_device *dev,
*value = wlan_hdd_get_fw_state(pHostapdAdapter);
break;
}
+ case QCSAP_CAP_TSF:
+ {
+ ret = hdd_capture_tsf(pHostapdAdapter, (uint32_t *)value, 1);
+ break;
+ }
default:
hddLog(LOGE, FL("Invalid getparam command %d"), sub_cmd);
ret = -EINVAL;
break;
-
}
return ret;
@@ -5625,6 +5685,16 @@ static const struct iw_priv_args hostapd_private_args[] = {
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getdfsnol" },
{ QCSAP_GET_ACL, 0,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_acl_list" },
+#ifdef WLAN_FEATURE_TSF
+ { QCSAP_CAP_TSF, 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "cap_tsf" },
+#endif
+ { QCSAP_IOCTL_SET_NONE_GET_THREE, 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, "" },
+#ifdef WLAN_FEATURE_TSF
+ { QCSAP_GET_TSF, 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, "get_tsf" },
+#endif
{ QCASAP_TX_CHAINMASK_CMD, 0,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_txchainmask" },
{ QCASAP_RX_CHAINMASK_CMD, 0,
@@ -5772,6 +5842,7 @@ static const struct iw_priv_args hostapd_private_args[] = {
static const iw_handler hostapd_private[] = {
[QCSAP_IOCTL_SETPARAM - SIOCIWFIRSTPRIV] = iw_softap_setparam, //set priv ioctl
[QCSAP_IOCTL_GETPARAM - SIOCIWFIRSTPRIV] = iw_softap_getparam, //get priv ioctl
+ [QCSAP_IOCTL_SET_NONE_GET_THREE - SIOCIWFIRSTPRIV] = iw_softap_get_three,
[QCSAP_IOCTL_GET_STAWPAIE - SIOCIWFIRSTPRIV] = iw_get_genie, //get station genIE
[QCSAP_IOCTL_SETWPAIE - SIOCIWFIRSTPRIV] = iw_softap_setwpsie,
[QCSAP_IOCTL_STOPBSS - SIOCIWFIRSTPRIV] = iw_softap_stopbss, // stop bss
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index fda069f1855a..5ed41aee1660 100755
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -134,6 +134,7 @@ void hdd_ch_avoid_cb(void *hdd_context,void *indi_param);
#include "wma.h"
#include "wlan_hdd_ocb.h"
+#include "wlan_hdd_tsf.h"
#if defined(LINUX_QCMBR)
#define SIOCIOCTLTX99 (SIOCDEVPRIVATE+13)
@@ -12002,6 +12003,8 @@ int hdd_wlan_startup(struct device *dev, v_VOID_t *hif_sc)
wlan_hdd_cfg80211_link_layer_stats_init(pHddCtx);
#endif
+ wlan_hdd_tsf_init(pHddCtx);
+
#ifdef WLAN_FEATURE_LPSS
wlan_hdd_send_all_scan_intf_info(pHddCtx);
wlan_hdd_send_version_pkg(pHddCtx->target_fw_version,
diff --git a/CORE/HDD/src/wlan_hdd_tsf.c b/CORE/HDD/src/wlan_hdd_tsf.c
new file mode 100644
index 000000000000..3bf5cd281529
--- /dev/null
+++ b/CORE/HDD/src/wlan_hdd_tsf.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2015 Qualcomm Atheros, Inc.
+ * All Rights Reserved.
+ * Qualcomm Atheros Confidential and Proprietary.
+ *
+ */
+
+
+/**
+ * wlan_hdd_tsf.c - WLAN Host Device Driver tsf related implementation
+ */
+
+#include "wlan_hdd_main.h"
+#include "wma_api.h"
+
+/**
+ * hdd_capture_tsf() - capture tsf
+ *
+ * @adapter: pointer to adapter
+ * @buf: pointer to uplayer buf
+ * @len : the length of buf
+ *
+ * This function returns tsf value to uplayer.
+ *
+ * Return: 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;
+
+ if (adapter == NULL || buf == NULL) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("invalid pointer"));
+ return -EINVAL;
+ }
+ if (len != 1)
+ return -EINVAL;
+
+ if (adapter->device_mode == WLAN_HDD_INFRA_STATION) {
+ hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+ if (hdd_sta_ctx->conn_info.connState !=
+ 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;
+ }
+ }
+ if (adapter->tsf_state == TSF_CAP_STATE) {
+ 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);
+ }
+ 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;
+
+ if (adapter == NULL || buf == NULL) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("invalid pointer"));
+ return -EINVAL;
+ }
+
+ if (len != 3)
+ return -EINVAL;
+
+ if (adapter->device_mode == WLAN_HDD_INFRA_STATION) {
+ 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;
+ buf[1] = 0;
+ buf[2] = 0;
+ return ret;
+ }
+ }
+ if (adapter->tsf_high == 0 && adapter->tsf_low == 0) {
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ FL("not getting tsf value"));
+ buf[0] = TSF_NOT_RETURNED_BY_FW;
+ buf[1] = 0;
+ buf[2] = 0;
+ } else {
+ buf[0] = TSF_RETURN;
+ buf[1] = adapter->tsf_low;
+ buf[2] = adapter->tsf_high;
+ adapter->tsf_state = TSF_IDLE;
+
+ ret = process_wma_set_command((int)adapter->sessionId,
+ (int)GEN_PARAM_RESET_TSF_GPIO,
+ adapter->sessionId,
+ GEN_CMD);
+
+ if (0 != ret) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, FL("tsf get fail "));
+ buf[0] = TSF_RESET_GPIO_FAIL;
+ }
+ hddLog(VOS_TRACE_LEVEL_INFO,
+ FL("get tsf cmd,status=%u, tsf_low=%u, tsf_high=%u"),
+ buf[0], buf[1], buf[2]);
+ }
+ return ret;
+}
+
+/**
+ * hdd_get_tsf_cb() - handle tsf callback
+ *
+ * @pcb_cxt: pointer to the hdd_contex
+ * @ptsf: pointer to struct stsf
+ *
+ * This function handle the event that reported by firmware at first.
+ * The event contains the vdev_id, current tsf value of this vdev,
+ * tsf value is 64bits, discripted in two varaible tsf_low and tsf_high.
+ * These two values each is uint32.
+ *
+ * Return: Describe the execute result of this routine
+ */
+static int hdd_get_tsf_cb(void *pcb_cxt, struct stsf *ptsf)
+{
+ hdd_context_t *hddctx;
+ hdd_adapter_t *adapter;
+ int status;
+
+ if (pcb_cxt == NULL || ptsf == NULL) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("HDD context is not valid"));
+ return -EINVAL;
+ }
+
+ hddctx = (hdd_context_t *)pcb_cxt;
+ status = wlan_hdd_validate_context(hddctx);
+ if (0 != status) {
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("hdd context is not valid"));
+ return -EINVAL;
+ }
+
+ adapter = hdd_get_adapter_by_vdev(hddctx, ptsf->vdev_id);
+
+ 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);
+
+ adapter->tsf_low = ptsf->tsf_low;
+ adapter->tsf_high = ptsf->tsf_high;
+
+ 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);
+ 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);
+}
diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c
index b1dd30a5e048..54009f03545c 100644
--- a/CORE/HDD/src/wlan_hdd_wext.c
+++ b/CORE/HDD/src/wlan_hdd_wext.c
@@ -108,6 +108,7 @@
#endif
#include "wlan_hdd_ocb.h"
+#include "wlan_hdd_tsf.h"
#ifdef FEATURE_OEM_DATA_SUPPORT
#define MAX_OEM_DATA_RSP_LEN 2047
@@ -304,6 +305,7 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { {2412, 1}, {2417, 2},
#define WE_GET_SCAN_BAND_PREFERENCE 55
#define WE_GET_TEMPERATURE 56
#define WE_GET_FW_STATUS 57
+#define WE_CAP_TSF 58
/* Private ioctls and their sub-ioctls */
#define WLAN_PRIV_SET_INT_GET_INT (SIOCIWFIRSTPRIV + 2)
@@ -402,7 +404,9 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { {2412, 1}, {2417, 2},
/* (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 */
@@ -6137,6 +6141,63 @@ static int __iw_setchar_getnone(struct net_device *dev,
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;
+}
+
+
static int iw_setchar_getnone(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
@@ -6682,7 +6743,11 @@ static int __iw_setnone_getint(struct net_device *dev,
*value = wlan_hdd_get_fw_state(pAdapter);
break;
}
-
+ case WE_CAP_TSF:
+ {
+ ret = hdd_capture_tsf(pAdapter, (uint32_t *)value, 1);
+ break;
+ }
default:
{
hddLog(LOGE, "Invalid IOCTL get_value command %d", value[0]);
@@ -9838,6 +9903,7 @@ static const iw_handler we_private[] = {
[WLAN_PRIV_GET_CHAR_SET_NONE - SIOCIWFIRSTPRIV] = iw_get_char_setnone,
[WLAN_PRIV_SET_NONE_GET_NONE - SIOCIWFIRSTPRIV] = iw_setnone_getnone, //action priv ioctl
[WLAN_PRIV_SET_VAR_INT_GET_NONE - SIOCIWFIRSTPRIV] = iw_set_var_ints_getnone,
+ [WLAN_PRIV_SET_NONE_GET_THREE_INT - SIOCIWFIRSTPRIV] = iw_setnone_get_threeint,
[WLAN_PRIV_ADD_TSPEC - SIOCIWFIRSTPRIV] = iw_add_tspec,
[WLAN_PRIV_DEL_TSPEC - SIOCIWFIRSTPRIV] = iw_del_tspec,
[WLAN_PRIV_GET_TSPEC - SIOCIWFIRSTPRIV] = iw_get_tspec,
@@ -10568,7 +10634,12 @@ static const struct iw_priv_args we_private_args[] = {
0,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
"get_fwstate"},
-
+#ifdef WLAN_FEATURE_TSF
+ { WE_CAP_TSF,
+ 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+ "cap_tsf"},
+#endif
/* handlers for main ioctl */
{ WLAN_PRIV_SET_CHAR_GET_NONE,
IW_PRIV_TYPE_CHAR| 512,
@@ -10619,7 +10690,17 @@ static const struct iw_priv_args we_private_args[] = {
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
0,
"setsapchannels" },
-
+ /* handlers for main ioctl */
+ { WLAN_PRIV_SET_NONE_GET_THREE_INT,
+ 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
+ "" },
+#ifdef WLAN_FEATURE_TSF
+ { WE_GET_TSF,
+ 0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
+ "get_tsf" },
+#endif
/* handlers for main ioctl */
{ WLAN_PRIV_GET_CHAR_SET_NONE,
0,
diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h
index 6ebb733baa0f..707fdc4302c7 100644
--- a/CORE/MAC/inc/sirApi.h
+++ b/CORE/MAC/inc/sirApi.h
@@ -5805,6 +5805,21 @@ struct tSirSapOffloadInfo
#endif /* SAP_AUTH_OFFLOAD */
/**
+ * struct stsf - the basic stsf structure
+ *
+ * @vdev_id: vdev id
+ * @tsf_low: low 32bits of tsf
+ * @tsf_high: high 32bits of tsf
+ *
+ * driver use this struct to store the tsf info
+ */
+struct stsf {
+ uint32_t vdev_id;
+ uint32_t tsf_low;
+ uint32_t tsf_high;
+};
+
+/**
* OCB structures
*/
diff --git a/CORE/MAC/inc/wniApi.h b/CORE/MAC/inc/wniApi.h
index 8a4343cb6a57..553711dc386b 100644
--- a/CORE/MAC/inc/wniApi.h
+++ b/CORE/MAC/inc/wniApi.h
@@ -391,6 +391,7 @@ enum eWniMsgTypes
eWNI_SME_DCC_UPDATE_NDL_RSP,
eWNI_SME_DCC_STATS_EVENT,
+ eWNI_SME_TSF_EVENT,
eWNI_SME_MSG_TYPES_END
};
diff --git a/CORE/SERVICES/COMMON/wma_api.h b/CORE/SERVICES/COMMON/wma_api.h
index e5118ac2b13b..9db03444432f 100644
--- a/CORE/SERVICES/COMMON/wma_api.h
+++ b/CORE/SERVICES/COMMON/wma_api.h
@@ -76,7 +76,9 @@ typedef enum {
#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG
GEN_PARAM_DUMP_PCIE_ACCESS_LOG
#endif
- GEN_PARAM_MODULATED_DTIM
+ GEN_PARAM_MODULATED_DTIM,
+ GEN_PARAM_CAPTURE_TSF,
+ GEN_PARAM_RESET_TSF_GPIO,
} GEN_PARAM;
#define VDEV_CMD 1
diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c
index 4187057e92f9..581cd7eaf785 100644
--- a/CORE/SERVICES/WMA/wma.c
+++ b/CORE/SERVICES/WMA/wma.c
@@ -7900,6 +7900,122 @@ VOS_STATUS WDA_GetSnr(tAniGetSnrReq *psnr_req)
return VOS_STATUS_SUCCESS;
}
+#ifdef WLAN_FEATURE_TSF
+/**
+ * wma_capture_tsf() - send wmi to fw to capture tsf
+ *
+ * @wma_handle: wma handler
+ * @vdev_id: vdev id
+ *
+ * Return: wmi send state
+ */
+static VOS_STATUS wma_capture_tsf(tp_wma_handle wma_handle, uint32_t vdev_id)
+{
+ VOS_STATUS vos_status = VOS_STATUS_SUCCESS;
+ wmi_buf_t buf;
+ wmi_vdev_tsf_tstamp_action_cmd_fixed_param *cmd;
+ int status;
+ int len = sizeof(*cmd);
+
+ buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
+ if (!buf) {
+ WMA_LOGP("%s: failed to allocate memory for cap tsf cmd",
+ __func__);
+ return VOS_STATUS_E_NOMEM;
+ }
+
+ cmd = (wmi_vdev_tsf_tstamp_action_cmd_fixed_param *) wmi_buf_data(buf);
+ cmd->vdev_id = vdev_id;
+ cmd->tsf_action = TSF_TSTAMP_CAPTURE_REQ;
+
+ WMA_LOGD("%s :vdev_id %u, TSF_TSTAMP_CAPTURE_REQ",
+ __func__, cmd->vdev_id);
+
+ WMITLV_SET_HDR(&cmd->tlv_header,
+ WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param,
+ WMITLV_GET_STRUCT_TLVLEN(
+ wmi_vdev_tsf_tstamp_action_cmd_fixed_param));
+
+ status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
+ len, WMI_VDEV_TSF_TSTAMP_ACTION_CMDID);
+ if (status != EOK) {
+ WMA_LOGE("wmi_unified_cmd_send returned Error %d", status);
+ vos_status = VOS_STATUS_E_FAILURE;
+ goto error;
+ }
+
+ return VOS_STATUS_SUCCESS;
+
+error:
+ if (buf)
+ adf_nbuf_free(buf);
+ return vos_status;
+}
+
+/**
+ * wma_reset_tsf_gpio() - send wmi to fw to reset GPIO
+ *
+ * @wma_handle: wma handler
+ * @vdev_id: vdev id
+ *
+ * Return: wmi send state
+ */
+static VOS_STATUS wma_reset_tsf_gpio(tp_wma_handle wma_handle, uint32_t vdev_id)
+{
+ VOS_STATUS vos_status = VOS_STATUS_SUCCESS;
+ wmi_buf_t buf;
+ wmi_vdev_tsf_tstamp_action_cmd_fixed_param *cmd;
+ int status;
+ int len = sizeof(*cmd);
+ uint8_t *buf_ptr;
+
+ buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
+ if (!buf) {
+ WMA_LOGP("%s: failed to allocate memory for reset tsf gpio",
+ __func__);
+ return VOS_STATUS_E_NOMEM;
+ }
+
+ buf_ptr = (u_int8_t *) wmi_buf_data(buf);
+ cmd = (wmi_vdev_tsf_tstamp_action_cmd_fixed_param *) buf_ptr;
+ cmd->vdev_id = vdev_id;
+ cmd->tsf_action = TSF_TSTAMP_CAPTURE_RESET;
+
+ WMA_LOGD("%s :vdev_id %u, TSF_TSTAMP_CAPTURE_RESET",
+ __func__, cmd->vdev_id);
+
+ WMITLV_SET_HDR(&cmd->tlv_header,
+ WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param,
+ WMITLV_GET_STRUCT_TLVLEN(
+ wmi_vdev_tsf_tstamp_action_cmd_fixed_param));
+
+ status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
+ len, WMI_VDEV_TSF_TSTAMP_ACTION_CMDID);
+
+ if (status != EOK) {
+ WMA_LOGE("wmi_unified_cmd_send returned Error %d", status);
+ vos_status = VOS_STATUS_E_FAILURE;
+ goto error;
+ }
+ return VOS_STATUS_SUCCESS;
+
+error:
+ if (buf)
+ adf_nbuf_free(buf);
+ return vos_status;
+}
+#else
+static VOS_STATUS wma_capture_tsf(tp_wma_handle wma_handle, uint32_t vdev_id)
+{
+ return VOS_STATUS_SUCCESS;
+}
+
+static VOS_STATUS wma_reset_tsf_gpio(tp_wma_handle wma_handle, uint32_t vdev_id)
+{
+ return VOS_STATUS_SUCCESS;
+}
+#endif
+
/* function : wma_start_scan
* Description :
* Args :
@@ -12363,6 +12479,12 @@ static void wma_process_cli_set_cmd(tp_wma_handle wma,
ret = wmi_crash_inject(wma->wmi_handle,
privcmd->param_value, privcmd->param_sec_value);
break;
+ case GEN_PARAM_CAPTURE_TSF:
+ ret = wma_capture_tsf(wma, privcmd->param_value);
+ break;
+ case GEN_PARAM_RESET_TSF_GPIO:
+ ret = wma_reset_tsf_gpio(wma, privcmd->param_value);
+ break;
#ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG
case GEN_PARAM_DUMP_PCIE_ACCESS_LOG:
HTCDump(wma->htc_handle, PCIE_DUMP, false);
@@ -26136,6 +26258,58 @@ static int wma_sap_ofl_del_sta_handler(void *handle, u_int8_t *data,
#endif /* SAP_AUTH_OFFLOAD */
/**
+ * wma_vdev_tsf_handler() - handle tsf event indicated by FW
+ *
+ * @handle: wma context
+ * @data: event buffer
+ * @data len: length of event buffer
+ *
+ * Return: 0 on success
+ */
+static int wma_vdev_tsf_handler(void *handle, uint8_t *data,
+ uint32_t data_len)
+{
+ vos_msg_t vos_msg = {0};
+ WMI_VDEV_TSF_REPORT_EVENTID_param_tlvs *param_buf;
+ wmi_vdev_tsf_report_event_fixed_param *tsf_event;
+ struct stsf *ptsf;
+
+ if (data == NULL) {
+ WMA_LOGE("%s: invalid pointer", __func__);
+ return -EINVAL;
+ }
+ ptsf = vos_mem_malloc(sizeof(*ptsf));
+ if (NULL == ptsf) {
+ WMA_LOGE("%s: failed to allocate sSirtsf memory", __func__);
+ return -ENOMEM;
+ }
+
+ param_buf = (WMI_VDEV_TSF_REPORT_EVENTID_param_tlvs *)data;
+ tsf_event = param_buf->fixed_param;
+
+ ptsf->vdev_id = tsf_event->vdev_id;
+ ptsf->tsf_low = tsf_event->tsf_low;
+ ptsf->tsf_high = tsf_event->tsf_high;
+
+ WMA_LOGD("%s: receive WMI_VDEV_TSF_REPORT_EVENTID ", __func__);
+ WMA_LOGD("%s: vdev_id = %u,tsf_low =%u, tsf_high = %u", __func__,
+ ptsf->vdev_id, ptsf->tsf_low, ptsf->tsf_high);
+
+ vos_msg.type = eWNI_SME_TSF_EVENT;
+ vos_msg.bodyptr = ptsf;
+ vos_msg.bodyval = 0;
+
+ if (VOS_STATUS_SUCCESS !=
+ vos_mq_post_message(VOS_MQ_ID_SME, &vos_msg)) {
+
+ WMA_LOGP("%s: Failed to post eWNI_SME_TSF_EVENT", __func__);
+ vos_mem_free(ptsf);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/**
* wma_echo_event_handler() - received echo response event from firmware
* @handle: wma context
* @event_buf: event buffer
@@ -26382,6 +26556,15 @@ VOS_STATUS wma_start(v_VOID_t *vos_ctx)
}
#endif /* SAP_AUTH_OFFLOAD */
+ status = wmi_unified_register_event_handler(wma_handle->wmi_handle,
+ WMI_VDEV_TSF_REPORT_EVENTID,
+ wma_vdev_tsf_handler);
+ if (0 != status) {
+ WMA_LOGP("%s: Failed to register tsf callback", __func__);
+ vos_status = VOS_STATUS_E_FAILURE;
+ goto end;
+ }
+
end:
WMA_LOGD("%s: Exit", __func__);
return vos_status;
diff --git a/CORE/SME/inc/smeInternal.h b/CORE/SME/inc/smeInternal.h
index f8c92c2906d0..9e63ec5e89cb 100644
--- a/CORE/SME/inc/smeInternal.h
+++ b/CORE/SME/inc/smeInternal.h
@@ -176,6 +176,10 @@ typedef struct tagSmeStruct
#ifdef WLAN_FEATURE_NAN
void (*nanCallback) (void*, tSirNanEvent*);
#endif
+
+ int (*get_tsf_cb)(void *pcb_cxt, struct stsf *ptsf);
+ void *get_tsf_cxt;
+
v_BOOL_t enableSelfRecovery;
tCsrLinkStatusCallback linkStatusCallback;
void *linkStatusContext;
diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h
index 9b32c5e75a03..1e887fe6cc67 100644
--- a/CORE/SME/inc/sme_Api.h
+++ b/CORE/SME/inc/sme_Api.h
@@ -4201,6 +4201,10 @@ eHalStatus sme_set_sap_auth_offload(tHalHandle hHal,
struct tSirSapOffloadInfo *sap_auth_offload_info);
#endif /* SAP_AUTH_OFFLOAD */
+eHalStatus sme_set_tsfcb(tHalHandle hHal,
+ int (*pcallbackfn)(void *pcallbackcontext, struct stsf *ptsf),
+ void *pcallbackcontext);
+
#ifdef WLAN_FEATURE_APFIND
VOS_STATUS sme_apfind_set_cmd(struct sme_ap_find_request_req *input);
#endif /* WLAN_FEATURE_APFIND */
diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c
index c86ef25793a7..87384683d409 100644
--- a/CORE/SME/src/sme_common/sme_Api.c
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -2872,6 +2872,16 @@ eHalStatus sme_ProcessMsg(tHalHandle hHal, vos_msg_t* pMsg)
vos_mem_free(pMsg->bodyptr);
}
break;
+ case eWNI_SME_TSF_EVENT:
+ if (pMac->sme.get_tsf_cb) {
+ pMac->sme.get_tsf_cb(pMac->sme.get_tsf_cxt,
+ (struct stsf *)pMsg->bodyptr);
+ }
+ if (pMsg->bodyptr) {
+ vos_mem_free(pMsg->bodyptr);
+ pMsg->bodyptr = NULL;
+ }
+ break;
#ifdef WLAN_FEATURE_NAN
case eWNI_SME_NAN_EVENT:
if (pMsg->bodyptr)
@@ -16150,3 +16160,31 @@ eHalStatus sme_configure_modulated_dtim(tHalHandle h_hal, tANI_U8 session_id,
return status;
}
+
+/**
+ * sme_set_tsfcb() - set callback which to handle WMI_VDEV_TSF_REPORT_EVENTID
+ *
+ * @hHal: Handler return by macOpen.
+ * @pcallbackfn: callback to handle the tsf event
+ * @pcallbackcontext: callback context
+ *
+ * Return: eHalStatus.
+ */
+eHalStatus sme_set_tsfcb
+(
+ tHalHandle hHal,
+ int (*pcallbackfn)(void *pcallbackcontext, struct stsf *pTsf),
+ void *pcallbackcontext
+)
+{
+ tpAniSirGlobal pMac = PMAC_STRUCT(hHal);
+ eHalStatus status;
+
+ status = sme_AcquireGlobalLock(&pMac->sme);
+ if (eHAL_STATUS_SUCCESS == status) {
+ pMac->sme.get_tsf_cb = pcallbackfn;
+ pMac->sme.get_tsf_cxt = pcallbackcontext;
+ sme_ReleaseGlobalLock(&pMac->sme);
+ }
+ return status;
+}
diff --git a/Kbuild b/Kbuild
index fcfa636df6df..9d897fa04de4 100644
--- a/Kbuild
+++ b/Kbuild
@@ -381,6 +381,10 @@ ifeq ($(CONFIG_QCOM_TDLS),y)
HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_tdls.o
endif
+ifeq ($(CONFIG_WLAN_SYNC_TSF),y)
+HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_tsf.o
+endif
+
############ EPPING ############
EPPING_DIR := CORE/EPPING
EPPING_INC_DIR := $(EPPING_DIR)/inc
@@ -1342,6 +1346,11 @@ ifeq ($(SAP_AUTH_OFFLOAD),1)
CDEFINES += -DSAP_AUTH_OFFLOAD
endif
+# Enable featue sync tsf between multi devices
+ifeq ($(CONFIG_WLAN_SYNC_TSF),y)
+CDEFINES += -DWLAN_FEATURE_TSF
+endif
+
# Enable target dump for non-qualcomm platform
ifeq ($(CONFIG_NON_QC_PLATFORM), y)
CDEFINES += -DCONFIG_NON_QC_PLATFORM
diff --git a/Kconfig b/Kconfig
index 35508dd4155d..31a48a0c90cc 100644
--- a/Kconfig
+++ b/Kconfig
@@ -45,4 +45,8 @@ config QCOM_LTE_COEX
bool "Enable QCOM LTE Coex feature"
default n
+config CONFIG_WLAN_SYNC_TSF
+ bool "Enable QCOM sync multi devices tsf feature"
+ default n
+
endif # QCA_CLD_WLAN