diff options
| author | kaliu <kaliu@qti.qualcomm.com> | 2015-04-22 14:51:13 +0800 |
|---|---|---|
| committer | AnjaneeDevi Kapparapu <c_akappa@qti.qualcomm.com> | 2015-04-22 17:04:17 +0530 |
| commit | 58afff5a4028b8a52a56f96ec45fdea35e29503e (patch) | |
| tree | 5804e5ed484b4d2543a52316a70a10fef5e03534 | |
| parent | d6667373b600ed00fc82de2a5d6a34ae5f16664a (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.h | 5 | ||||
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_main.h | 8 | ||||
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_tsf.h | 48 | ||||
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_wext.h | 32 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_hostapd.c | 75 | ||||
| -rwxr-xr-x | CORE/HDD/src/wlan_hdd_main.c | 3 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_tsf.c | 207 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_wext.c | 89 | ||||
| -rw-r--r-- | CORE/MAC/inc/sirApi.h | 15 | ||||
| -rw-r--r-- | CORE/MAC/inc/wniApi.h | 1 | ||||
| -rw-r--r-- | CORE/SERVICES/COMMON/wma_api.h | 4 | ||||
| -rw-r--r-- | CORE/SERVICES/WMA/wma.c | 183 | ||||
| -rw-r--r-- | CORE/SME/inc/smeInternal.h | 4 | ||||
| -rw-r--r-- | CORE/SME/inc/sme_Api.h | 4 | ||||
| -rw-r--r-- | CORE/SME/src/sme_common/sme_Api.c | 38 | ||||
| -rw-r--r-- | Kbuild | 9 | ||||
| -rw-r--r-- | Kconfig | 4 |
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; +} @@ -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 @@ -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 |
