qcacld-3.0: Add gettime of PTP for NON-QC platform

Implement NON-QC platform TSF and TSF PLUS.
Implement gettime of PTP.
Implement TSF PLUS for SAP/GO

CRs-Fixed: 2399624
Change-Id: Id4f41a94256a8f035ae408c168c246569185c534
This commit is contained in:
Subrat Dash 2019-02-12 16:28:14 +05:30 • committed by nshrivas
commit 5f36fbef77
15 changed files with 548 additions and 49 deletions

2
Kbuild
View file

@ -2209,6 +2209,8 @@ cppflags-$(CONFIG_FEATURE_HL_GROUP_CREDIT_FLOW_CONTROL) += -DFEATURE_HL_GROUP_CR
cppflags-$(CONFIG_FEATURE_HL_DBS_GROUP_CREDIT_SHARING) += -DFEATURE_HL_DBS_GROUP_CREDIT_SHARING
cppflags-$(CONFIG_CREDIT_REP_THROUGH_CREDIT_UPDATE) += -DCONFIG_CREDIT_REP_THROUGH_CREDIT_UPDATE
cppflags-$(CONFIG_WLAN_SYNC_TSF_PTP) += -DWLAN_FEATURE_TSF_PTP
cppflags-$(CONFIG_WLAN_SYNC_TSF_PLUS_EXT_GPIO_IRQ) += -DWLAN_FEATURE_TSF_PLUS_EXT_GPIO_IRQ
cppflags-$(CONFIG_TX_DESC_HI_PRIO_RESERVE) += -DCONFIG_TX_DESC_HI_PRIO_RESERVE
#Enable FW logs through ini

View file

@ -158,6 +158,7 @@ struct wlan_fwol_neighbor_report_cfg {
* @enable_fw_module_log_level_num: enablefw module log level num
* @is_rate_limit_enabled: Enable/disable RA rate limited
* @tsf_gpio_pin: TSF GPIO Pin config
* @tsf_irq_host_gpio_pin: TSF GPIO Pin config
* @tsf_ptp_options: TSF Plus feature options config
* @lprx_enable: LPRx feature enable config
* @sae_enable: SAE feature enable config
@ -196,6 +197,9 @@ struct wlan_fwol_cfg {
uint32_t tsf_gpio_pin;
#ifdef WLAN_FEATURE_TSF_PLUS
uint32_t tsf_ptp_options;
#ifdef WLAN_FEATURE_TSF_PLUS_EXT_GPIO_IRQ
uint32_t tsf_irq_host_gpio_pin;
#endif
#endif
#endif
bool lprx_enable;

View file

@ -356,6 +356,32 @@ static void ucfg_fwol_init_tsf_ptp_options(struct wlan_objmgr_psoc *psoc,
}
#endif
#ifdef WLAN_FEATURE_TSF_PLUS_EXT_GPIO_IRQ
/**
* ucfg_fwol_fetch_tsf_irq_host_gpio_pin: Populate the
* tsf_irq_host_gpio_pin from cfg
* @psoc: The global psoc handler
* @fwol_cfg: The cfg structure
*
* This function is used to populate the cfg value of host platform
* gpio pin configured to receive tsf interrupt from fw.
*
* Return: none
*/
static void
ucfg_fwol_fetch_tsf_irq_host_gpio_pin(struct wlan_objmgr_psoc *psoc,
struct wlan_fwol_cfg *fwol_cfg)
{
fwol_cfg->tsf_irq_host_gpio_pin =
cfg_get(psoc, CFG_SET_TSF_IRQ_HOST_GPIO_PIN);
}
#else
static void
ucfg_fwol_fetch_tsf_irq_host_gpio_pin(struct wlan_objmgr_psoc *psoc,
struct wlan_fwol_cfg *fwol_cfg)
{
}
#endif
/**
* ucfg_fwol_init_sae_cfg: Populate the sae control config from cfg
* @psoc: The global psoc handler
@ -448,6 +474,7 @@ QDF_STATUS fwol_cfg_on_psoc_enable(struct wlan_objmgr_psoc *psoc)
fwol_init_adapt_dwelltime_in_cfg(psoc, &fwol_cfg->dwelltime_params);
ucfg_fwol_fetch_ra_filter(psoc, fwol_cfg);
ucfg_fwol_fetch_tsf_gpio_pin(psoc, fwol_cfg);
ucfg_fwol_fetch_tsf_irq_host_gpio_pin(psoc, fwol_cfg);
ucfg_fwol_fetch_dhcp_server_settings(psoc, fwol_cfg);
return status;

View file

@ -434,6 +434,34 @@
CFG_VALUE_OR_DEFAULT, \
"GPIO pin to toggle when capture tsf")
#ifdef WLAN_FEATURE_TSF_PLUS_EXT_GPIO_IRQ
/* <ini>
* gtsf_irq_host_gpio_pin
* @Min: 0
* @Max: 254
* @Default: 255
*
* TSF irq GPIO pin of host platform
*
* Related: None
*
* Usage: Internal
*
* </ini>
*/
#define CFG_SET_TSF_IRQ_HOST_GPIO_PIN CFG_INI_INT( \
"gtsf_irq_host_gpio_pin", \
0, \
254, \
255, \
CFG_VALUE_OR_DEFAULT, \
"TSF irq GPIO pin of host platform")
#define __CFG_SET_TSF_IRQ_HOST_GPIO_PIN CFG(CFG_SET_TSF_IRQ_HOST_GPIO_PIN)
#else
#define __CFG_SET_TSF_IRQ_HOST_GPIO_PIN
#endif
#if defined(WLAN_FEATURE_TSF) && defined(WLAN_FEATURE_TSF_PLUS)
/* <ini>
* gtsf_ptp_options: TSF Plus feature options
@ -464,6 +492,7 @@
0xf, \
CFG_VALUE_OR_DEFAULT, \
"TSF Plus feature options")
#define __CFG_SET_TSF_PTP_OPT CFG(CFG_SET_TSF_PTP_OPT)
#else
#define __CFG_SET_TSF_PTP_OPT
@ -655,6 +684,7 @@
CFG(CFG_ENABLE_FW_MODULE_LOG_LEVEL) \
CFG(CFG_RA_FILTER_ENABLE) \
CFG(CFG_SET_TSF_GPIO_PIN) \
__CFG_SET_TSF_IRQ_HOST_GPIO_PIN \
__CFG_SET_TSF_PTP_OPT \
CFG(CFG_LPRX) \
__CFG_IS_SAE_ENABLED \

View file

@ -304,6 +304,19 @@ QDF_STATUS ucfg_fwol_get_is_rate_limit_enabled(struct wlan_objmgr_psoc *psoc,
QDF_STATUS ucfg_fwol_get_tsf_gpio_pin(struct wlan_objmgr_psoc *psoc,
uint32_t *tsf_gpio_pin);
#ifdef WLAN_FEATURE_TSF_PLUS_EXT_GPIO_IRQ
/**
* ucfg_fwol_get_tsf_irq_host_gpio_pin() - Assigns tsf_irq_host_gpio_pin value
* @psoc: pointer to the psoc object
*
* Return: QDF Status
*/
QDF_STATUS
ucfg_fwol_get_tsf_irq_host_gpio_pin(struct wlan_objmgr_psoc *psoc,
uint32_t *tsf_irq_host_gpio_pin);
#endif
#ifdef DHCP_SERVER_OFFLOAD
/**
* ucfg_fwol_get_enable_dhcp_server_offload()-Assign enable_dhcp_server_offload

View file

@ -558,6 +558,27 @@ QDF_STATUS ucfg_fwol_get_tsf_ptp_options(struct wlan_objmgr_psoc *psoc,
*tsf_ptp_options = fwol_obj->cfg.tsf_ptp_options;
return QDF_STATUS_SUCCESS;
}
#ifdef WLAN_FEATURE_TSF_PLUS_EXT_GPIO_IRQ
QDF_STATUS
ucfg_fwol_get_tsf_irq_host_gpio_pin(struct wlan_objmgr_psoc *psoc,
uint32_t *tsf_irq_host_gpio_pin)
{
struct wlan_fwol_psoc_obj *fwol_obj;
fwol_obj = fwol_get_psoc_obj(psoc);
if (!fwol_obj) {
fwol_err("Failed to get FWOL obj");
*tsf_irq_host_gpio_pin =
cfg_default(CFG_SET_TSF_IRQ_HOST_GPIO_PIN);
return QDF_STATUS_E_FAILURE;
}
*tsf_irq_host_gpio_pin = fwol_obj->cfg.tsf_irq_host_gpio_pin;
return QDF_STATUS_SUCCESS;
}
#endif
#endif
#else
QDF_STATUS ucfg_fwol_get_tsf_gpio_pin(struct wlan_objmgr_psoc *psoc,
@ -571,6 +592,7 @@ QDF_STATUS ucfg_fwol_get_tsf_ptp_options(struct wlan_objmgr_psoc *psoc,
{
return QDF_STATUS_E_NOSUPPORT;
}
#endif
QDF_STATUS ucfg_fwol_get_lprx_enable(struct wlan_objmgr_psoc *psoc,
@ -594,6 +616,7 @@ bool ucfg_fwol_get_sae_enable(struct wlan_objmgr_psoc *psoc)
{
return cfg_get(psoc, CFG_IS_SAE_ENABLED);
}
#else
bool ucfg_fwol_get_sae_enable(struct wlan_objmgr_psoc *psoc)
{

View file

@ -47,6 +47,13 @@ ifeq ($(CONFIG_DEBUG_FS), y)
CONFIG_WLAN_POWER_DEBUGFS := y
endif
ifeq ($(CONFIG_NETWORK_PHY_TIMESTAMPING), y)
CONFIG_WLAN_SYNC_TSF_PLUS := y
CONFIG_WLAN_SYNC_TSF_PTP := y
CONFIG_WLAN_SYNC_TSF_PLUS_EXT_GPIO_IRQ := y
endif
ifeq ($(CONFIG_SLUB_DEBUG_ON), y)
CONFIG_DESC_DUP_DETECT_DEBUG := y
CONFIG_DEBUG_RX_RING_BUFFER := y

View file

@ -46,6 +46,12 @@ ifeq ($(CONFIG_DEBUG_FS), y)
CONFIG_WLAN_POWER_DEBUGFS := n
endif
ifeq ($(CONFIG_NETWORK_PHY_TIMESTAMPING), y)
CONFIG_WLAN_SYNC_TSF_PLUS := y
CONFIG_WLAN_SYNC_TSF_PTP := y
CONFIG_WLAN_SYNC_TSF_PLUS_EXT_GPIO_IRQ := y
endif
ifeq ($(CONFIG_SLUB_DEBUG_ON), y)
CONFIG_DESC_DUP_DETECT_DEBUG := n
CONFIG_DEBUG_RX_RING_BUFFER := n

View file

@ -27,6 +27,12 @@ ifeq ($(CONFIG_DEBUG_FS), y)
CONFIG_WLAN_POWER_DEBUGFS := y
endif
ifeq ($(CONFIG_NETWORK_PHY_TIMESTAMPING), y)
CONFIG_WLAN_SYNC_TSF_PLUS := y
CONFIG_WLAN_SYNC_TSF_PTP := y
CONFIG_WLAN_SYNC_TSF_PLUS_EXT_GPIO_IRQ := y
endif
# Features gets enabled on slub debug
CONFIG_WLAN_DEBUG_CRASH_INJECT := y
CONFIG_FEATURE_MEMDUMP_ENABLE := y

View file

@ -32,6 +32,11 @@ CONFIG_FEATURE_UNIT_TEST_SUSPEND := n
CONFIG_LEAK_DETECTION := n
endif
ifeq ($(CONFIG_NETWORK_PHY_TIMESTAMPING), y)
CONFIG_WLAN_SYNC_TSF_PLUS := y
CONFIG_WLAN_SYNC_TSF_PTP := y
CONFIG_WLAN_SYNC_TSF_PLUS_EXT_GPIO_IRQ := y
endif
CONFIG_ENABLE_SIZE_OPTIMIZE := y

View file

@ -61,6 +61,10 @@
#if defined(WLAN_OPEN_SOURCE) && defined(CONFIG_HAS_WAKELOCK)
#include <linux/wakelock.h>
#endif
#ifdef WLAN_FEATURE_TSF_PTP
#include <linux/ptp_classify.h>
#include <linux/ptp_clock_kernel.h>
#endif
#include <wlan_hdd_ftm.h>
#include "wlan_hdd_tdls.h"
#include "wlan_hdd_tsf.h"
@ -1806,6 +1810,10 @@ struct hdd_context {
qdf_atomic_t cap_tsf_flag;
/* the context that is capturing tsf */
struct hdd_adapter *cap_tsf_context;
#endif
#ifdef WLAN_FEATURE_TSF_PTP
struct ptp_clock_info ptp_cinfo;
struct ptp_clock *ptp_clock;
#endif
uint8_t bt_a2dp_active:1;
uint8_t bt_vo_active:1;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
* Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@ -316,4 +316,15 @@ void hdd_capture_req_timer_expired_handler(void *arg)
}
#endif
#ifdef WLAN_FEATURE_TSF_PTP
/**
* wlan_get_ts_info() - return ts info to uplayer
* @dev: pointer to net_device
* @info: pointer to ethtool_ts_info
*
* Return: Describe the execute result of this routine
*/
int wlan_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info);
#endif
#endif

View file

@ -36,6 +36,7 @@
#include <cds_sched.h>
#include <linux/etherdevice.h>
#include "osif_sync.h"
#include <linux/ethtool.h>
#include <wlan_hdd_includes.h>
#include <qc_sap_ioctl.h>
#include "osif_sync.h"
@ -1896,6 +1897,7 @@ QDF_STATUS hdd_hostapd_sap_event_cb(struct sap_event *sap_event,
ap_ctx->operating_channel);
hostapd_state->bss_state = BSS_START;
hdd_start_tsf_sync(adapter);
/* Set default key index */
hdd_debug("default key index %hu", ap_ctx->wep_def_key_idx);
@ -2642,6 +2644,7 @@ stopbss:
* re-enabled
*/
hostapd_state->bss_state = BSS_STOP;
hdd_stop_tsf_sync(adapter);
#ifdef FEATURE_WLAN_AUTO_SHUTDOWN
wlan_hdd_auto_shutdown_enable(hdd_ctx, true);
@ -3162,6 +3165,12 @@ sap_restart:
}
#endif
#ifdef WLAN_FEATURE_TSF_PTP
static const struct ethtool_ops wlan_hostapd_ethtool_ops = {
.get_ts_info = wlan_get_ts_info,
};
#endif
const struct net_device_ops net_ops_struct = {
.ndo_open = hdd_hostapd_open,
.ndo_stop = hdd_hostapd_stop,
@ -3175,10 +3184,18 @@ const struct net_device_ops net_ops_struct = {
.ndo_select_queue = hdd_select_queue,
};
#ifdef WLAN_FEATURE_TSF_PTP
void hdd_set_ap_ops(struct net_device *dev)
{
dev->netdev_ops = &net_ops_struct;
dev->ethtool_ops = &wlan_hostapd_ethtool_ops;
}
#else
void hdd_set_ap_ops(struct net_device *dev)
{
dev->netdev_ops = &net_ops_struct;
}
#endif
bool hdd_sap_create_ctx(struct hdd_adapter *adapter)
{

View file

@ -79,6 +79,7 @@
#include <linux/ctype.h>
#include <linux/compat.h>
#include <linux/reboot.h>
#include <linux/ethtool.h>
#ifdef MSM_PLATFORM
#include <soc/qcom/subsystem_restart.h>
#endif
@ -3743,6 +3744,12 @@ static void hdd_set_multicast_list(struct net_device *net_dev)
osif_vdev_sync_op_stop(vdev_sync);
}
#ifdef WLAN_FEATURE_TSF_PTP
static const struct ethtool_ops wlan_ethtool_ops = {
.get_ts_info = wlan_get_ts_info,
};
#endif
static const struct net_device_ops wlan_drv_ops = {
.ndo_open = hdd_open,
.ndo_stop = hdd_stop,
@ -3764,6 +3771,7 @@ static const struct net_device_ops wlan_mon_drv_ops = {
.ndo_get_stats = hdd_get_stats,
};
#ifdef WLAN_FEATURE_TSF_PTP
/**
* hdd_set_station_ops() - update net_device ops for monitor mode
* @dev: Handle to struct net_device to be updated.
@ -3771,17 +3779,37 @@ static const struct net_device_ops wlan_mon_drv_ops = {
*/
void hdd_set_station_ops(struct net_device *dev)
{
if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam())
if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE) {
dev->netdev_ops = &wlan_mon_drv_ops;
} else {
dev->netdev_ops = &wlan_drv_ops;
dev->ethtool_ops = &wlan_ethtool_ops;
}
}
#else
void hdd_set_station_ops(struct net_device *dev)
{
if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE)
dev->netdev_ops = &wlan_mon_drv_ops;
else
dev->netdev_ops = &wlan_drv_ops;
}
#endif
#else
#ifdef WLAN_FEATURE_TSF_PTP
void hdd_set_station_ops(struct net_device *dev)
{
dev->netdev_ops = &wlan_drv_ops;
dev->ethtool_ops = &wlan_ethtool_ops;
}
#else
void hdd_set_station_ops(struct net_device *dev)
{
dev->netdev_ops = &wlan_drv_ops;
}
#endif
#endif
/**
* hdd_alloc_station_adapter() - allocate the station hdd adapter

View file

@ -27,6 +27,10 @@
#include "wlan_fwol_ucfg_api.h"
#include <qca_vendor.h>
#include <linux/errqueue.h>
#ifdef WLAN_FEATURE_TSF_PLUS_EXT_GPIO_IRQ
#include <linux/gpio.h>
static int tsf_gpio_irq_num = -1;
#endif
#include "ol_txrx_api.h"
static struct completion tsf_sync_get_completion_evt;
@ -35,6 +39,16 @@ static struct completion tsf_sync_get_completion_evt;
#define WLAN_HDD_CAPTURE_TSF_INIT_INTERVAL_MS 100
#define WLAN_HDD_SOFTAP_INTERVEL_TIMES 100
#ifdef WLAN_FEATURE_TSF_PLUS
#ifdef WLAN_FEATURE_TSF_PLUS_NOIRQ
static void hdd_update_timestamp(struct hdd_adapter *adapter);
#else
static void
hdd_update_timestamp(struct hdd_adapter *adapter,
uint64_t target_time, uint64_t host_time);
#endif
#endif
/**
* enum hdd_tsf_op_result - result of tsf operation
*
@ -116,6 +130,7 @@ static bool hdd_tsf_is_initialized(struct hdd_adapter *adapter)
return true;
}
#if defined(WLAN_FEATURE_TSF_PLUS_NOIRQ) && defined(WLAN_FEATURE_TSF_PLUS)
/**
* hdd_tsf_reset_gpio() - Reset TSF GPIO used for host timer sync
* @adapter: pointer to adapter
@ -125,7 +140,6 @@ static bool hdd_tsf_is_initialized(struct hdd_adapter *adapter)
*
* Return: TSF_RETURN on Success, TSF_RESET_GPIO_FAIL on failure
*/
#if defined(WLAN_FEATURE_TSF_PLUS_NOIRQ) && defined(WLAN_FEATURE_TSF_PLUS)
static int hdd_tsf_reset_gpio(struct hdd_adapter *adapter)
{
/* No GPIO Host timer sync for integrated WIFI Device */
@ -145,7 +159,54 @@ static QDF_STATUS hdd_tsf_set_gpio(struct hdd_context *hdd_ctx)
{
return QDF_STATUS_SUCCESS;
}
#else
static int hdd_tsf_reset_gpio(struct hdd_adapter *adapter)
{
int ret;
ret = wma_cli_set_command((int)adapter->vdev_id,
(int)GEN_PARAM_RESET_TSF_GPIO,
adapter->vdev_id,
GEN_CMD);
if (ret != 0) {
hdd_err("tsf reset GPIO fail ");
ret = TSF_RESET_GPIO_FAIL;
} else {
ret = TSF_RETURN;
}
return ret;
}
/**
* hdd_tsf_set_gpio() - Set TSF GPIO used for host timer sync
* @hdd_ctx: pointer to hdd context
*
* This function check GPIO and set GPIO as IRQ to FW side on
* none Adrastea arch
*
* Return: QDF_STATUS_SUCCESS on Success, others on Failure.
*/
static QDF_STATUS hdd_tsf_set_gpio(struct hdd_context *hdd_ctx)
{
QDF_STATUS status;
uint32_t tsf_gpio_pin = TSF_GPIO_PIN_INVALID;
status = ucfg_fwol_get_tsf_gpio_pin(hdd_ctx->psoc, &tsf_gpio_pin);
if (QDF_IS_STATUS_ERROR(status))
return QDF_STATUS_E_INVAL;
if (tsf_gpio_pin == TSF_GPIO_PIN_INVALID)
return QDF_STATUS_E_INVAL;
status = sme_set_tsf_gpio(hdd_ctx->mac_handle,
tsf_gpio_pin);
return status;
}
#endif
#ifdef WLAN_FEATURE_TSF_PLUS
bool hdd_tsf_is_ptp_enabled(struct hdd_context *hdd)
{
uint32_t tsf_ptp_options;
@ -200,51 +261,6 @@ bool hdd_tsf_is_dbg_fs_set(struct hdd_context *hdd)
else
return false;
}
#else
static int hdd_tsf_reset_gpio(struct hdd_adapter *adapter)
{
int ret;
ret = wma_cli_set_command((int)adapter->vdev_id,
(int)GEN_PARAM_RESET_TSF_GPIO, adapter->vdev_id,
GEN_CMD);
if (ret != 0) {
hdd_err("tsf reset GPIO fail ");
ret = TSF_RESET_GPIO_FAIL;
} else {
ret = TSF_RETURN;
}
return ret;
}
/**
* hdd_tsf_set_gpio() - Set TSF GPIO used for host timer sync
* @hdd_ctx: pointer to hdd context
*
* This function check GPIO and set GPIO as IRQ to FW side on
* none Adrastea arch
*
* Return: QDF_STATUS_SUCCESS on Success, others on Failure.
*/
static QDF_STATUS hdd_tsf_set_gpio(struct hdd_context *hdd_ctx)
{
QDF_STATUS status;
uint32_t tsf_gpio_pin = TSF_GPIO_PIN_INVALID;
status = ucfg_fwol_get_tsf_gpio_pin(hdd_ctx->psoc, &tsf_gpio_pin);
if (QDF_IS_STATUS_ERROR(status))
return QDF_STATUS_E_INVAL;
if (tsf_gpio_pin == TSF_GPIO_PIN_INVALID)
return QDF_STATUS_E_INVAL;
status = sme_set_tsf_gpio(hdd_ctx->mac_handle,
tsf_gpio_pin);
return status;
}
#endif
static enum hdd_tsf_op_result hdd_capture_tsf_internal(
@ -387,7 +403,11 @@ static enum hdd_tsf_op_result hdd_indicate_tsf_internal(
/* to distinguish 32-bit overflow case, this inverval should:
* equal or less than (1/2 * OVERFLOW_INDICATOR32 us)
*/
#ifdef WLAN_FEATURE_TSF_PLUS_EXT_GPIO_IRQ
#define WLAN_HDD_CAPTURE_TSF_INTERVAL_SEC 2
#else
#define WLAN_HDD_CAPTURE_TSF_INTERVAL_SEC 10
#endif
#define OVERFLOW_INDICATOR32 (((int64_t)0x1) << 32)
#define CAP_TSF_TIMER_FIX_SEC 1
@ -674,6 +694,9 @@ static irqreturn_t hdd_tsf_captured_irq_handler(int irq, void *arg)
if (!arg)
return IRQ_NONE;
if (irq != tsf_gpio_irq_num)
return IRQ_NONE;
hdd_ctx = (struct hdd_context *)arg;
host_time = hdd_get_monotonic_host_time(hdd_ctx);
@ -1344,6 +1367,99 @@ enum hdd_tsf_op_result wlan_hdd_tsf_plus_deinit(struct hdd_context *hdd_ctx)
return HDD_TSF_OP_SUCC;
}
#else
#ifdef WLAN_FEATURE_TSF_PLUS_EXT_GPIO_IRQ
static
enum hdd_tsf_op_result wlan_hdd_tsf_plus_init(struct hdd_context *hdd_ctx)
{
int ret;
QDF_STATUS status;
uint32_t tsf_irq_gpio_pin = TSF_GPIO_PIN_INVALID;
if (!hdd_tsf_is_ptp_enabled(hdd_ctx)) {
hdd_info("To enable TSF_PLUS, set gtsf_ptp_options in ini");
goto fail;
}
status = ucfg_fwol_get_tsf_irq_host_gpio_pin(hdd_ctx->psoc,
&tsf_irq_gpio_pin);
if (QDF_IS_STATUS_ERROR(status)) {
hdd_err("tsf gpio irq host pin error");
goto fail;
}
if (tsf_irq_gpio_pin == TSF_GPIO_PIN_INVALID) {
hdd_err("gpio host pin is invalid");
goto fail;
}
ret = gpio_request(tsf_irq_gpio_pin, "wlan_tsf");
if (ret) {
hdd_err("gpio host pin is invalid");
goto fail;
}
ret = gpio_direction_input(tsf_irq_gpio_pin);
if (ret) {
hdd_err("gpio host pin is invalid");
goto fail_free_gpio;
}
tsf_gpio_irq_num = gpio_to_irq(tsf_irq_gpio_pin);
if (tsf_gpio_irq_num < 0) {
hdd_err("fail to get irq: %d", tsf_gpio_irq_num);
goto fail_free_gpio;
}
ret = request_irq(tsf_gpio_irq_num, hdd_tsf_captured_irq_handler,
IRQF_SHARED | IRQF_TRIGGER_RISING, "wlan_tsf",
hdd_ctx);
if (ret) {
hdd_err("Failed to register irq handler: %d", ret);
goto fail_free_gpio;
}
if (hdd_tsf_is_tx_set(hdd_ctx))
ol_register_timestamp_callback(hdd_tx_timestamp);
return HDD_TSF_OP_SUCC;
fail_free_gpio:
gpio_free(tsf_irq_gpio_pin);
fail:
tsf_gpio_irq_num = -1;
return HDD_TSF_OP_FAIL;
}
static
enum hdd_tsf_op_result wlan_hdd_tsf_plus_deinit(struct hdd_context *hdd_ctx)
{
QDF_STATUS status;
uint32_t tsf_irq_gpio_pin = TSF_GPIO_PIN_INVALID;
if (!hdd_tsf_is_ptp_enabled(hdd_ctx))
return HDD_TSF_OP_SUCC;
status = ucfg_fwol_get_tsf_irq_host_gpio_pin(hdd_ctx->psoc,
&tsf_irq_gpio_pin);
if (QDF_IS_STATUS_ERROR(status))
return QDF_STATUS_E_INVAL;
if (tsf_irq_gpio_pin == TSF_GPIO_PIN_INVALID)
return QDF_STATUS_E_INVAL;
if (hdd_tsf_is_tx_set(hdd_ctx))
ol_deregister_timestamp_callback();
if (tsf_gpio_irq_num >= 0) {
free_irq(tsf_gpio_irq_num, hdd_ctx);
tsf_gpio_irq_num = -1;
gpio_free(tsf_irq_gpio_pin);
}
return HDD_TSF_OP_SUCC;
}
#else
static inline
enum hdd_tsf_op_result wlan_hdd_tsf_plus_init(struct hdd_context *hdd_ctx)
{
@ -1392,6 +1508,7 @@ enum hdd_tsf_op_result wlan_hdd_tsf_plus_deinit(struct hdd_context *hdd_ctx)
}
#endif
#endif
void hdd_tsf_notify_wlan_state_change(struct hdd_adapter *adapter,
eConnectionState old_state,
eConnectionState new_state)
@ -1448,6 +1565,197 @@ int hdd_indicate_tsf(struct hdd_adapter *adapter, uint32_t *buf, int len)
return __hdd_indicate_tsf(adapter, buf, len);
}
#ifdef WLAN_FEATURE_TSF_PTP
int wlan_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info)
{
struct hdd_adapter *adapter = netdev_priv(dev);
struct osif_vdev_sync *vdev_sync;
struct hdd_context *hdd_ctx;
int errno;
hdd_ctx = WLAN_HDD_GET_CTX(adapter);
errno = wlan_hdd_validate_context(hdd_ctx);
if (errno)
return -EINVAL;
errno = osif_vdev_sync_op_start(dev, &vdev_sync);
if (errno)
return -EAGAIN;
info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
SOF_TIMESTAMPING_RX_HARDWARE |
SOF_TIMESTAMPING_RAW_HARDWARE;
if (hdd_ctx->ptp_clock)
info->phc_index = ptp_clock_index(hdd_ctx->ptp_clock);
else
info->phc_index = -1;
osif_vdev_sync_op_stop(vdev_sync);
return 0;
}
#if (KERNEL_VERSION(4, 1, 0) > LINUX_VERSION_CODE)
/**
* wlan_ptp_gettime() - return fw ts info to uplayer
* @ptp: pointer to ptp_clock_info.
* @ts: pointer to timespec.
*
* Return: Describe the execute result of this routine
*/
static int wlan_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
{
uint64_t host_time, target_time = 0;
struct hdd_context *hdd_ctx;
struct hdd_adapter *adapter;
uint32_t tsf_reg_read_enabled;
struct osif_psoc_sync *psoc_sync;
int errno, status = 0;
hdd_ctx = qdf_container_of(ptp, struct hdd_context, ptp_cinfo);
errno = wlan_hdd_validate_context(hdd_ctx);
if (errno)
return -EINVAL;
errno = osif_psoc_sync_op_start(hdd_ctx->parent_dev, &psoc_sync);
if (errno)
return -EAGAIN;
adapter = hdd_get_adapter(hdd_ctx, QDF_P2P_GO_MODE);
if (!adapter) {
adapter = hdd_get_adapter(hdd_ctx, QDF_P2P_CLIENT_MODE);
if (!adapter) {
adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
if (!adapter)
adapter = hdd_get_adapter(hdd_ctx,
QDF_STA_MODE);
if (!adapter) {
status = -EOPNOTSUPP;
goto end;
}
}
}
host_time = hdd_get_monotonic_host_time(hdd_ctx);
if (hdd_get_targettime_from_hosttime(adapter, host_time,
&target_time)) {
hdd_err("get invalid target timestamp");
status = -EINVAL;
goto end;
}
*ts = ns_to_timespec(target_time * NSEC_PER_USEC);
end:
osif_psoc_sync_op_stop(psoc_sync);
return status;
}
/**
* wlan_hdd_phc_init() - phc init
* @hdd_ctx: pointer to the hdd_contex.
*
* Return: NULL
*/
static void wlan_hdd_phc_init(struct hdd_context *hdd_ctx)
{
hdd_ctx->ptp_cinfo.gettime = wlan_ptp_gettime;
hdd_ctx->ptp_clock = ptp_clock_register(&hdd_ctx->ptp_cinfo,
hdd_ctx->parent_dev);
}
/**
* wlan_hdd_phc_deinit() - phc deinit
* @hdd_ctx: pointer to the hdd_contex.
*
* Return: NULL
*/
static void wlan_hdd_phc_deinit(struct hdd_context *hdd_ctx)
{
hdd_ctx->ptp_cinfo.gettime = NULL;
if (hdd_ctx->ptp_clock) {
ptp_clock_unregister(hdd_ctx->ptp_clock);
hdd_ctx->ptp_clock = NULL;
}
}
#else
static int wlan_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
{
uint64_t host_time, target_time = 0;
struct hdd_context *hdd_ctx;
struct hdd_adapter *adapter;
struct osif_psoc_sync *psoc_sync;
int errno, status = 0;
hdd_ctx = qdf_container_of(ptp, struct hdd_context, ptp_cinfo);
errno = wlan_hdd_validate_context(hdd_ctx);
if (errno)
return -EINVAL;
errno = osif_psoc_sync_op_start(hdd_ctx->parent_dev, &psoc_sync);
if (errno)
return -EAGAIN;
adapter = hdd_get_adapter(hdd_ctx, QDF_P2P_GO_MODE);
if (!adapter) {
adapter = hdd_get_adapter(hdd_ctx, QDF_P2P_CLIENT_MODE);
if (!adapter) {
adapter = hdd_get_adapter(hdd_ctx, QDF_SAP_MODE);
if (!adapter)
adapter = hdd_get_adapter(hdd_ctx,
QDF_STA_MODE);
if (!adapter) {
status = -EOPNOTSUPP;
goto end;
}
}
}
host_time = hdd_get_monotonic_host_time(hdd_ctx);
if (hdd_get_targettime_from_hosttime(adapter, host_time,
&target_time)) {
hdd_err("get invalid target timestamp");
status = -EINVAL;
goto end;
}
*ts = ns_to_timespec64(target_time * NSEC_PER_USEC);
end:
osif_psoc_sync_op_stop(psoc_sync);
return status;
}
static void wlan_hdd_phc_init(struct hdd_context *hdd_ctx)
{
hdd_ctx->ptp_cinfo.gettime64 = wlan_ptp_gettime;
hdd_ctx->ptp_clock = ptp_clock_register(&hdd_ctx->ptp_cinfo,
hdd_ctx->parent_dev);
}
static void wlan_hdd_phc_deinit(struct hdd_context *hdd_ctx)
{
hdd_ctx->ptp_cinfo.gettime64 = NULL;
if (hdd_ctx->ptp_clock) {
ptp_clock_unregister(hdd_ctx->ptp_clock);
hdd_ctx->ptp_clock = NULL;
}
}
#endif
#else
static void wlan_hdd_phc_init(struct hdd_context *hdd_ctx)
{
}
static void wlan_hdd_phc_deinit(struct hdd_context *hdd_ctx)
{
}
#endif /* WLAN_FEATURE_TSF_PTP */
/**
* hdd_get_tsf_cb() - handle tsf callback
* @pcb_cxt: pointer to the hdd_contex
@ -1516,6 +1824,7 @@ int hdd_get_tsf_cb(void *pcb_cxt, struct stsf *ptsf)
adapter->cur_tsf_sync_soc_time =
qdf_log_timestamp_to_usecs(tsf_sync_soc_time) * NSEC_PER_USEC;
complete(&tsf_sync_get_completion_evt);
hdd_update_tsf(adapter, adapter->cur_target_time);
hdd_info("Vdev=%u, tsf_low=%u, tsf_high=%u ptsf->soc_timer_low=%u ptsf->soc_timer_high=%u",
@ -1550,7 +1859,7 @@ static int __wlan_hdd_cfg80211_handle_tsf_cmd(struct wiphy *wiphy,
struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_TSF_MAX + 1];
int status, ret;
struct sk_buff *reply_skb;
uint32_t tsf_op_resp[3], tsf_cmd;
uint32_t tsf_op_resp[3] = {0}, tsf_cmd;
hdd_enter_dev(wdev->netdev);
@ -1699,6 +2008,8 @@ void wlan_hdd_tsf_init(struct hdd_context *hdd_ctx)
if (wlan_hdd_tsf_plus_init(hdd_ctx) != HDD_TSF_OP_SUCC)
goto fail;
wlan_hdd_phc_init(hdd_ctx);
return;
fail:
@ -1713,6 +2024,7 @@ void wlan_hdd_tsf_deinit(struct hdd_context *hdd_ctx)
if (!qdf_atomic_read(&hdd_ctx->tsf_ready_flag))
return;
wlan_hdd_phc_deinit(hdd_ctx);
wlan_hdd_tsf_plus_deinit(hdd_ctx);
qdf_atomic_set(&hdd_ctx->tsf_ready_flag, 0);
qdf_atomic_set(&hdd_ctx->cap_tsf_flag, 0);